
#include "Webserv.hpp"
#define MAX_FILESIZE 1 * MB // unused

// const?
/*
	https://www.rfc-editor.org/rfc/rfc9110.html#name-get
*/
void	Webserv::_get(Client *client, std::string &path)
{
	std::cout << "_get()\n";
	if (eval_file_type(path) == IS_DIR)
	{
		if (path[path.size() - 1] != '/')
			path.push_back('/');
		for (size_t i = 0; i < client->assigned_location->index.size(); i++)
		{
			if (eval_file_type(path + client->assigned_location->index[i]) == IS_FILE)
			{
				path.append(client->assigned_location->index[i]);
				_get_file(client, path);
				std::cerr << "Added an index\n"; //debug
				return ;
			}
		}
		if (client->assigned_location->autoindex == true)
			_autoindex(client, path);
		else
			client->status = 404;
	}
	else
		_get_file(client, 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.
*/
void	Webserv::_get_file(Client *client, const std::string &path)
{
	std::ifstream		ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ?
	std::stringstream	buf;

	std::cout << "_get_file()\n";

	client->status = ::eval_file_access(path, R_OK);
	if (client->status)
		return;

	ifd.open(path.c_str());
	if (!ifd)
	{
		std::cerr << path << ": ifd.open fail" << '\n';
		client->status = 500;
	}
	else
	{
		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);
		}
	}
}

/*
// WIP Low priority : Chunk or not chunk (if filesize > MAX_FILESIZE)
// WITH flag "std::ios::ate" for open()
std::streampos	size = ifd.tellg();
ifd.seekg(0, std::ios::beg);
if (size > MAX_FILESIZE)
{
	// Chunked GET here
	return ;
}
*/


// const?
void	Webserv::_autoindex(Client *client, const std::string &path)
{
	std::cout << "_autoindex()\n";

	std::string		dir_list;
	DIR				*dir;
	struct dirent	*ent;

	// std::cout << "Path in auto is: " << path << '\n';
	if ( (dir = opendir(path.c_str()) ) != NULL)
	{
		dir_list.append(AUTOINDEX_START);
		dir_list.append(path);
		dir_list.append(AUTOINDEX_MID1);
		dir_list.append(path);
		dir_list.append(AUTOINDEX_MID2);
		while ((ent = readdir (dir)) != NULL)
		{
			if (strcmp(".", ent->d_name) == 0)
				continue ;
			dir_list.append("<a style=\"font-size:1.5em\" href=\"");
			dir_list.append(client->get_rq_abs_path());
			if (dir_list[dir_list.size() - 1] != '/')
				dir_list.push_back('/');
			dir_list.append(ent->d_name);
			dir_list.append("\">");
			dir_list.append(ent->d_name);
			if (ent->d_type == DT_DIR)
				dir_list.append("/");
			dir_list.append("</a>");
			dir_list.append("\n");
		}

// <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);
		closedir (dir);
		client->status = 200;
		_append_body(client, dir_list, "html");
	}
	else
	{
		client->status = 500;
		perror("could not open dir");
		return ;
	}
}

std::string	Webserv::_determine_file_extension(const std::string &path) const
{
	size_t	dot_pos = path.rfind(".");
	if (dot_pos != NPOS && dot_pos + 1 < path.size())
		return ( path.substr(dot_pos + 1) );
	return (std::string(""));
}
