
#include "Webserv.hpp"

void	Webserv::_get(Client *client)
{
/* RULES **

if path is a valid dir check if index is specified and serve that
if no index and autoindex, server that
if file, server that!

Where does cgi fit in in all this ???

*/

	std::string		path = client->get_rq_abs_path();

	// this might not be the best thing, a voir
//	path.insert(0, client->assigned_location->root);

//client->assigned_location->path

	path.replace(0, client->assigned_location->path.size(), client->assigned_location->root);

	std::cerr << "path = " << path << "\n";

	// path = root + location.path
	// we will tack on an index if there is a valid one
	// or autoindex if allowed
	// or let _get_file sort out the error otherwise.

// change this cuz 
//	if (path_is_valid(client->assigned_location->root) == 2)
//		_get_file(...);
	if (path_is_valid(path) == 1)
	{
	//	std::cout << "path is valid\n";
		if (path[path.size() - 1] != '/')
			path.push_back('/');
		for (size_t i = 0; i < client->assigned_location->index.size(); i++)
		{
//			std::cout << "location path: " << client->assigned_location->path << '\n';
//			std::cout << "location index: " << client->assigned_location->index[i] << '\n';
//			std::cout << "path with index: " << path + assigned_location->index[i] << '\n';
			if (path_is_valid(path + client->assigned_location->index[i]) == 2)
			{
	//			std::cout << "found a valid index\n";
				path.append(client->assigned_location->index[i]);
				_get_file(client, path);
				return ;
			}
		}
		if (client->assigned_location->autoindex == true)
		{
			_autoindex(client, path);
			return ;
		}
	}
//	else
//		_get_file(client, path);
	// what about cgi ???



	// TMP HUGO
	//
	std::string	script_output;
	if (_is_cgi(client))
	{
		script_output = _exec_cgi(client);
		// DEBUG
		std::cout << "\n____script_output____\n" << script_output << "\n_______________\n";
		// wip check output of script
		_check_script_output(client, script_output);
		client->response += script_output;
		return;
	}
	//
	// END TMP HUGO

	_get_file(client, path);
}

# define MAX_FILESIZE 1000000 // (1Mo)
void	Webserv::_get_file(Client *client, const std::string &path)
{
/*
	std::ios::binary
	https://gcc.gnu.org/onlinedocs/libstdc++/manual/fstreams.html#std.io.filestreams.binary
	tldr : its seems to not be so simple to do read/write of binary file in a portable way.
*/
	std::ifstream		ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ?
	std::stringstream	buf;

	std::cout << "made it to get_file\n";

	if (access(path.c_str(), F_OK) == -1)
	{
		std::perror("err access()");
		client->status = 404;
		return ;
	}

	if (access(path.c_str(), R_OK) == -1)
	{
		std::perror("err access()");
		client->status = 403;
		return ;
	}

	ifd.open(path.c_str(), std::ios::ate);
	if (!ifd)
	{
		std::cerr << path << ": ifd.open fail" << '\n';
		client->status = 500;
	}
	else
	{
		/* std::streampos	size = ifd.tellg();
		// WIP Low priority : Chunk or not chunk (if filesize too big)
		if (size > MAX_FILESIZE)
		{
			// Then chunk
			client->status = 500; // WIP temp
			std::cerr << "File too large for non chunk body\n";
			return ;
		} */

		ifd.seekg(0, std::ios::beg);
		buf << ifd.rdbuf();
		if (!ifd || !buf)
		{
			std::cerr << path << ": ifd.read fail" << '\n';
			client->status = 500;
		}
		else
		{
			client->status = 200;
			std::string	file_ext = _determine_file_extension(path);
			_append_body(client, buf.str(), file_ext);
		}
	}
}

// i only sort of need &path...
// def can improve but works for now...
//void	Webserv::_autoindex(Client *client, LocationConfig &location, std::string &path)
void	Webserv::_autoindex(Client *client, std::string &path)
{
//	std::cout << "made it to _autoindex\n";

	(void)path;
	std::string		dir_list;
	DIR				*dir;
	struct dirent	*ent;

//	std::cout << "location root: " << client->assigned_location->root << " location path: "
//		<< client->assigned_location->path << '\n';

//	if ((dir = opendir (path.c_str())) != NULL)
	if ((dir = opendir ((client->assigned_location->root + client->assigned_location->path).c_str())) != NULL)
	{
	/* print all the files and directories within directory */
		dir_list.append(AUTOINDEX_START);
		dir_list.append(client->assigned_location->path);
		dir_list.append(AUTOINDEX_MID1);
		dir_list.append(client->assigned_location->path);
		dir_list.append(AUTOINDEX_MID2);
		while ((ent = readdir (dir)) != NULL)
		{
			if (strcmp(".", ent->d_name) == 0)
				continue ;
			dir_list.append("<a href=\"");
			dir_list.append(client->assigned_location->path.c_str());
			dir_list.append(ent->d_name);
			dir_list.append("\">");
			dir_list.append(ent->d_name);
			dir_list.append("</a>");
			dir_list.append("\r\n");	// is this right?
		}

// <a href="http://nginx.org/">nginx.org</a>.<br/>
// <a href="/test/test_deeper/index1.html">index1.html</a>

// apparently this is more than good enough!
// <a href="/test/test_deeper/..">..</a>

		dir_list.append(AUTOINDEX_END);
//		std::cout << "\n\n" << dir_list << '\n';
		closedir (dir);
		_append_body(client, dir_list, "html");
	}
	else
	{
		// in theory not possible cuz we already checked...
	/* could not open directory */
//	perror ("");
		std::cout << "could not open dir\n";
		return ;
	}
}
