#include "HttpServer.h"

#ifdef _WIN32
#include "WinsockServer.h"
#else
#include "UnixSocketServer.h"
#endif

#include "Socket.h"
#include "AbstractWebApp.h"

#include "HttpRequest.h"
#include "HttpResponse.h"
#include "FileLogger.h"

HttpServer::HttpServer()
{
#ifdef _WIN32
	mSocketServer = std::make_unique<WinsockServer>();
#else
	mSocketServer = std::make_unique<UnixSocketServer>();
#endif
}

HttpServer::~HttpServer()
{

}

void HttpServer::onConnection(Socket* socket)
{
	auto message = socket->recieve();

	if (socket->getState().mConnectStatus == Socket::State::ConnectStatus::OK)
	{
		MLOG_INFO("Got client content: " << message);

		HttpRequest request;
		request.fromString(message);

		std::string extra_bytes;
		if (request.requiredBytes() > 0)
		{
			extra_bytes += socket->recieve();
		}

		auto response = mWebApp->onHttpRequest(request);
		socket->respond(response.toString());
	}
	else if (socket->getState().mConnectStatus == Socket::State::ConnectStatus::UNSET)
	{
		MLOG_INFO("Client closed connection");
	}
	else
	{
		MLOG_INFO("Connection error");
	}
}

void HttpServer::onFailure(const std::string& reason)
{
	MLOG_ERROR("Connection failed: " << reason);
}

void HttpServer::run(AbstractWebApp* webApp, Address mListenAddress)
{
	mWebApp = webApp;

	PlatformSocketServer::Address socket_address;
	socket_address.mHost = mListenAddress.mHost;
	socket_address.mPort = mListenAddress.mPort;
	socket_address.mPrefix = mListenAddress.mPrefix;

	auto on_connection = [this](Socket* socket)
	{
		this->onConnection(socket);
	};

	auto on_failure = [this](const PlatformSocketServer::Result& result)
	{
		this->onFailure(result.mErrorMessage);
	};

	mSocketServer->listen(socket_address, on_connection, on_failure);

	mSocketServer->shutDown();
}