
#include "Webserv.hpp"

bool	Webserv::_is_cgi(Client *client)
{
	// TODO see how it works with config
	if (client->fill_script_path("/cgi-bin/php-cgi"))
		return true;
	if (client->fill_script_path("/cgi-bin/cgi_cpp.cgi"))
		return true;
	return false;
}

void	Webserv::_exec_cgi(Client *client)
{
	char**	env;

	env = _set_env(client);
	_exec_script(client, env);

	for (int i = 0; env[i]; i++)
		delete[] env[i];
	delete[] env;
}

char*	Webserv::_dup_env(std::string var, std::string val = "")
{
	std::string str;

	str = var + "=" + val;
	return ( strdup(str.c_str()) );
}

char*	Webserv::_dup_env(std::string var, int i)
{
	std::string str;
	std::string val;

	val = ::itos(i);
	str = var + "=" + val;
	// TODO change strdup for something with new
	return ( strdup(str.c_str()) );
}

char**	Webserv::_set_env(Client *client)
{
	char**	env = new char*[19];

	env[0]  = _dup_env("AUTH_TYPE");		// authentification not supported
	env[1]  = _dup_env("CONTENT_LENGTH"		, client->get_rq_body().size());
	env[2]  = _dup_env("CONTENT_TYPE"		, client->get_rq_headers("Content-Type"));
	env[3]  = _dup_env("GATEWAY_INTERFACE"	, "CGI/1.0");
	env[4]  = _dup_env("PATH_INFO"			, client->get_rq_script_info());
	env[5]  = _dup_env("PATH_TRANSLATED");	// not supported
	env[6]  = _dup_env("QUERY_STRING"		, client->get_rq_query());
	env[7]  = _dup_env("REMOTE_ADDR"		, client->get_cl_ip());
	env[8]  = _dup_env("REMOTE_HOST"		, client->get_rq_headers("Host")); // just test
	env[9]  = _dup_env("REMOTE_IDENT");		// authentification not supported
	env[10] = _dup_env("REMOTE_USER");		// authentification not supported
	env[11] = _dup_env("REQUEST_METHOD"		, client->get_rq_method_str());
	env[12] = _dup_env("SCRIPT_NAME"		, client->get_rq_script_path());
	env[13] = _dup_env("SERVER_NAME"		, client->get_rq_hostname());
	env[14] = _dup_env("SERVER_PORT"		, client->get_rq_port());
	env[15] = _dup_env("SERVER_PROTOCOL"	, client->get_rq_version());
	env[16] = _dup_env("SERVER_SOFTWARE"	, "webser/1.0");
	env[17] = _dup_env("REDIRECT_STATUS"	, "200");
	env[18] = NULL;

	return env;
}

void	Webserv::_exec_script(Client *client, char **env)
{
	#define RD 0
	#define WR 1
	#define CGI_BUF_SIZE 10
	#define FD_WR_TO_CHLD fd_in[WR]
	#define FD_WR_TO_PRNT fd_out[WR]
	#define FD_RD_FR_CHLD fd_out[RD]
	#define FD_RD_FR_PRNT fd_in[RD]

	pid_t			pid;
	char			buf[CGI_BUF_SIZE]; // WIP define buffer
	char * const *	nll = NULL;
	std::string		response;
	std::string		body = client->get_rq_body();
	int				fd_in[2];
	int				fd_out[2];

	pipe(fd_in);
	pipe(fd_out);

	pid = fork();
	if (pid == -1)
		std::cerr << "fork crashed" << std::endl;
	else if (pid == 0)
	{   
		close(FD_WR_TO_CHLD);
		close(FD_RD_FR_CHLD);
		dup2(FD_RD_FR_PRNT, STDIN_FILENO);
		dup2(FD_WR_TO_PRNT, STDOUT_FILENO);
		execve(client->get_rq_script_path().c_str(), nll, env);
		std::cerr << "execve crashed.\n";
	}
	else
	{
		close(FD_RD_FR_PRNT);
		close(FD_WR_TO_PRNT);
		write(FD_WR_TO_CHLD, body.c_str(), body.size());
		close(FD_WR_TO_CHLD);
		waitpid(-1, NULL, 0);

		memset(buf, '\0', CGI_BUF_SIZE);
		while (read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE - 1) > 0)
		{
			response += buf;
			memset(buf, '\0', CGI_BUF_SIZE);
		}
	}
	if (response.empty())
		response = "Status: 500\r\n\r\n";

// DEBUG
std::cout	<< "\n_______response_______\n"
			<< response
			<< "\n_____end response_____\n";

	// TODO: see how this must be handled
	client->response += response;
}

