
#include "Client.hpp"

/*********************************************
 * COPLIENS
 *********************************************/

Client::Client( ) {
	return;
}

Client::~Client() {
	return;
}

// copy constructor :
// Client::Client( Client const & src ) {}

// assignement operator :
// Client &	Client::operator=( Client const & rhs ) {}



/*********************************************
 * PUBLIC MEMBER FUNCTIONS
 *********************************************/

// http headers :
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers
// https://www.ibm.com/docs/en/cics-ts/5.3?topic=protocol-http-requests
// https://www.tutorialspoint.com/http/http_requests.htm
void	Client::parse_request()
{
	std::string							sub;
	std::vector<std::string>			list;
	size_t								pos;

	pos = (raw_request).find(CRLF CRLF);
	sub = (raw_request).substr(0, pos);
	list = split(sub, '\n');
	// request_line
	_parse_request_line(*list.begin());
	list.erase(list.begin());
	// headers
	_parse_request_headers(list);
	//body- message
	_parse_request_body(pos +  4);

	// add "raw_request.clear()" after parsing ? for little less memory usage ?
}

void	Client::clear()
{
	clear_request();
	raw_request.clear();
	response.clear();
	status = 0;
}

void	Client::clear_request()
{
	_request.method = UNKNOWN;
	_request.path.clear();
	_request.version.clear();
	_request.headers.clear();
	_request.body.clear();
}

http_method	Client::get_method()  { return _request.method; }
std::string	&Client::get_path()    { return _request.path; }
std::string	&Client::get_version() { return _request.version; }
std::string	&Client::get_body()    { return _request.body; }
std::string	&Client::get_headers(const std::string &key) { return _request.headers[key]; }

/*********************************************
 * PRIVATE MEMBER FUNCTIONS
 *********************************************/

void	Client::_parse_request_line( std::string rline )
{
	std::vector<std::string>	sline;
	std::string					tmp;

	sline = split(rline, ' ');
	if (sline.size() != 3)
	{
		std::cerr << "err _parse_request_line(): ";
		throw std::runtime_error("bad request-line header");
	}
	// method
	tmp = ::trim(sline[0], ' ');
	tmp = ::trim(tmp, '\r');
	_request.method = str_to_http_method(tmp);
	// TODO uri in request_line
	// https://www.rfc-editor.org/rfc/rfc7230#section-5.3
	// https://stackoverflow.com/questions/40311306/when-is-absoluteuri-used-from-the-http-request-specs
	tmp = ::trim(sline[1], ' ');
	tmp = ::trim(tmp, '\r');
	_request.path = tmp;
	// http version
	tmp = ::trim(sline[2], ' ');
	tmp = ::trim(tmp, '\r');
	_request.version = tmp;
}

void	Client::_parse_request_headers( std::vector<std::string> list )
{
	std::string							key;
	std::string							val;
	std::vector<std::string>::iterator	it;
	size_t								pos;

	for (it = list.begin(); it != list.end(); it++)
	{
		pos = (*it).find(':');
		key = (*it).substr( 0, pos );
		key = ::trim(key, ' ');
		key = ::trim(key, '\r');
		val = (*it).substr( pos + 1 );
		val = ::trim(val, ' ');
		val = ::trim(val, '\r');
		_request.headers.insert( std::pair<std::string, std::string>(key, val) );
	}
}

void	Client::_parse_request_body( size_t pos )
{
	std::string body = &raw_request[pos];

	_request.body = body;
}

/*********************************************
 * OVERLOAD
 *********************************************/

bool	operator==(const Client& lhs, const Client& rhs)
	{ return lhs.fd == rhs.fd; }

bool	operator==(const Client& lhs, int fd)
	{ return lhs.fd == fd; }

bool	operator==(int fd, const Client& rhs)
	{ return fd == rhs.fd; }
