#include "cgi_utils.hpp"

std::string	str_tolower(std::string str)
{
	std::transform(str.begin(), str.end(), str.begin(), ::tolower);
	return str;
}

std::string	trim(std::string str, char del)
{
	size_t	pos;

	// delete leadings del
	pos = str.find_first_not_of(del);
	if (pos == NPOS)
		pos = str.size();
	str = str.substr(pos);

	// delete trailing del
	pos = str.find_last_not_of(del);
	if (pos != NPOS)
		str = str.substr(0, pos + 1);

	return str;
}

std::vector<std::string>
	split(const std::string & input, std::string delim, char ctrim)
{
	std::vector<std::string>	split_str;
	std::string					tmp;
	size_t						start = 0;
	size_t						end = 0;
	size_t						len = 0;

	while (end != NPOS)
	{
		end = input.find(delim, start);
		len = end - start;
		if (end == NPOS)
			len = end;
		tmp = input.substr(start, len);
		if (ctrim != '\0')
			tmp = trim(tmp, ctrim);
		if (tmp.size() != 0)
			split_str.push_back( tmp );
		start = end + delim.size();
	}
	return split_str;
}

std::string	itos(int n)
{
	std::stringstream	strs;

	strs << n;
	return ( strs.str() );
}

std::string	parse_env(const std::string & env)
{
	std::string ret = "";
	char *		ret_env;

	ret_env = getenv(env.c_str());
	if (ret_env != NULL)
		ret = ret_env;

	return ret;
}

std::string print_env(char **env, std::string tag)
{
	std::string	ret = "";

	for (int i = 0; env[i] != NULL; ++i)
	{
		ret += "<" + tag + ">";
		ret += env[i];
		ret += "</" + tag + "><br>";
	}
	return ret;
}

std::string
	print_form(std::string form, std::string tag_key, std::string tag_val)
{
	std::vector<std::string>                    split_str;
	std::vector<std::string>                    sub_split_str;
	std::vector<std::string>::const_iterator    it;
	std::string									ret = "";
	std::string									key;

	split_str = split(form, "&");
	for (it = split_str.begin(); it != split_str.end(); ++it)
	{
		sub_split_str = split(*it, "=");
		key = sub_split_str[0];
		if (key == "fname")
			key = "first name";
		else if (key == "lname")
			key = "last name";
		ret += "<br><" + tag_key + ">" + key + ": </" + tag_key + ">";
		ret += "<" + tag_val + ">" + sub_split_str[1] + "</" + tag_val + ">";
	}
	return ret;
}

std::string	get_form_infos(const std::string & rq_body)
{
	std::string form_infos;
	std::string method;

	method = parse_env("REQUEST_METHOD");

	if (method == "POST")
		form_infos = rq_body;
	else if (method == "GET")
		form_infos = parse_env("QUERY_STRING");

	return form_infos;
}

std::string	get_value(const std::string & key, const std::string & rq_body)
{
	std::string	infos;
	std::string	ret;
	size_t		pos;
	size_t      end;
	size_t      len;

	infos = get_form_infos(rq_body);
	pos = str_tolower(infos).find(str_tolower(key));
	if (pos == NPOS)
		return "";
	pos = infos.find_first_of("=", pos);
	if (pos == NPOS)
		return "";
	pos++;
	end = infos.find_first_of("&", pos);
	if (end == NPOS)
		end = infos.size();
	len = end - pos;
	ret = infos.substr(pos, len);

	return ret;
}

void
	fill_body_basic(char **env, std::string & http_body, const std::string & rq_body)
{
	std::string rq_method = "not found";
	std::string rq_query;
	std::string form_infos;

	rq_method = parse_env("REQUEST_METHOD");
	rq_query = parse_env("QUERY_STRING");

	if (rq_method == "POST")
		form_infos = rq_body;
	else if (rq_method == "GET")
		form_infos = rq_query;

	http_body  = HTML_BODY_TOP;

	http_body += "<br><h3>method used: </h3>";
	http_body += "<p>" + rq_method + "</p>";

	http_body += "<br><h3>form body: </h3>";
	http_body += "<p>" + rq_body + "</p>";

	http_body += "<br><h3>form query: </h3>";
	http_body += "<p>" + rq_query + "</p>";

	http_body += "<br><br><h3>output:</h3><br>";
	http_body += print_form(form_infos, "p", "p");

	http_body += "<br><br><h3>cgi_env_variables:</h3><br>";
	http_body += print_env(env, "p");

	http_body += HTML_BODY_BOTTOM;
}

size_t	eval_file_access(const std::string &path, int mode)
{
	if (::access(path.c_str(), F_OK) == -1)
	{
		std::perror("err access()");
		return 404; // NOT_FOUND, file doesn't exist
	}

	if (::access(path.c_str(), mode) == -1)
	{
		std::perror("err access()");
		return 403; // FORBIDDEN, file doesn't have access permission
	}
	return 0;
}

