#include "HttpServer.hpp"

HttpServer::HttpServer(int port, const char *pDocDir)
: Thread("Http")
, m_port(port)
, m_docDir(pDocDir)
{
	startThread();
}


HttpServer::~HttpServer(void)
{
	stopThread(10000);
}

void HttpServer::addListener(IHttpListener *pListener)
{
	m_listeners.add(pListener);
}

const char* HttpServer::getDocName(char *buffer, int buflen)
{
	static char docBuffer[1024];
	char *pDoc = docBuffer;
	char *pBuf;
	bool hasQuery = false;

	strcpy(docBuffer, m_docDir);
	pDoc = &docBuffer[strlen(docBuffer)];
	*pDoc = '\\';
	pDoc++;

	if (!stricmp(buffer, "GET"))
	{
		return nullptr;
	}

	pBuf = buffer + 3;
	while(*pBuf == 0x20)
		pBuf++;

	while(*pBuf == '/')
		pBuf++;

	int len = 0;
	while(*pBuf != 0x20)
	{
		if (*pBuf == '?')
		{
			hasQuery = true;
			break;
		}
		*pDoc++ = *pBuf++;
		len++;
	}
	*pDoc = 0;

	if (hasQuery)
	{
		m_viewFormat.parse(pBuf);
	}

	if (len==0)
		return nullptr;

	return docBuffer;
}

void HttpServer::run()
{
	char buffer[1024];
	char docname[1024];

	ScopedPointer<StreamingSocket> listenSock = new StreamingSocket();
	listenSock->createListener(m_port);

	while(!threadShouldExit())
	{
		const char *pDoc = nullptr;
		if (listenSock->waitUntilReady(true, 100) > 0)
		{

			ScopedPointer<StreamingSocket> pSock = listenSock->waitForNextConnection();
		
			int numRead = pSock->read(buffer, sizeof(buffer), false);
			if (numRead > 0)
			{
				pDoc = getDocName(buffer, numRead);
				if (!pDoc)
				{
					pDoc = docname;
					sprintf(docname, "%s\\welcome.htm", m_docDir);
				}
				else
				{
					m_listeners.call(&IHttpListener::onUpdate, pDoc, m_viewFormat);
				}
			}

			ScopedPointer<juce::File> file = new juce::File(pDoc);
			if (!file)
				continue;

			ScopedPointer<juce::FileInputStream> pFileStream = file->createInputStream();
			if (!pFileStream)
				continue;

			int64 remain = pFileStream->getTotalLength();
			int64 toRead;

			while(remain)
			{
				toRead = remain;
				if (toRead > sizeof(buffer))
				{
					toRead = sizeof(buffer);
				}
				pFileStream->read(buffer, toRead);
				pSock->write(buffer, toRead);
				remain -= toRead;
			}
			pFileStream = nullptr;
			pSock = nullptr;
			file = nullptr;
		}
	}
}
