
#include "Webserv.hpp"

// Arbitrary values
#define BUFSIZE 8192 // (8Ko)
#define MAX_HEADER_SIZE 16384 // (16Ko)

enum read_return
{
	READ_IN_PROGRESS,
	READ_COMPLETE,
	READ_CLOSE,
};

void	Webserv::_request(Client *client)
{
	int ret = _read_request(client);

	if (g_last_signal)
		_handle_last_signal();

	if (ret == READ_CLOSE)
	{
		_close_client(client->get_cl_fd());
	}
	else if (ret == READ_COMPLETE)
	{
		_epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_MOD);
	}
}

int	Webserv::_read_request(Client *client) // Messy, Need refactoring
{
	char	buf[BUFSIZE];
	ssize_t	ret;

	std::cerr << "call recv()" << "\n" ;
	ret = ::recv(client->get_cl_fd(), buf, BUFSIZE, 0);
	std::cerr << "recv() on fd(" << client->get_cl_fd() << ") returned = " << ret << "\n" ;
	if (ret == -1)
	{
		std::perror("err recv()");
		std::cerr << "client ptr =" << client << "\n"; // DEBUG
		std::cerr << "client.fd =" << client->get_cl_fd() << "\n"; // DEBUG
		return READ_CLOSE;
	}
	if (ret == 0)
	{
		std::cerr << "recv() read 0, then close client" << "\n"; // DEBUG
		return READ_CLOSE;
	}

	client->raw_request.append(buf, ret);
	if (!client->header_complete)
	{
		if (client->raw_request.find(CRLF CRLF) != std::string::npos)
		{
			client->header_complete = true;
			client->parse_request(_servers);
			std::cerr << client->get_rq_method_str() << " " << client->get_rq_uri() << " " << client->get_rq_version() << "\n"; // DEBUG
			if (client->status)
				return READ_COMPLETE;

			if (client->get_rq_headers("Content-Type").empty() && client->get_rq_headers("Content-Length").empty()) // No body case
				return READ_COMPLETE;
		}
		else if (client->raw_request.size() > MAX_HEADER_SIZE)
		{
			// 413 or 400 ? 413 seems common among http server, but don't fit perfectly.
			client->status = 413;
			return READ_COMPLETE;
		}
	}
	else if (client->header_complete)
	{
		client->read_body_size += ret;
		if (client->read_body_size > client->assigned_server->client_body_limit)
		{
			client->status = 413;
			return READ_COMPLETE;
		}
		if ((int)client->read_body_size >= ::atoi(client->get_rq_headers("Content-Length").c_str()))
		{
			client->parse_request_body();
			return READ_COMPLETE;
		}
	}

	return READ_IN_PROGRESS;
}
