
#include <string.h>

#include "client.h"
#include "sender.h"
#include "receiver.h"
#include "sockets.h"
#include "threads.h"
//#include <vld.h>

// --------------------------------
// --------------------------------

// --------------------------------

sender :: sender(sockets :: clientSocket* cs) : workerSemaphore_(0, 268435456)
{
	cs_ = cs;
}

// --------------------------------

void sender :: send(char *msg)
{
    listLock_.lock();

	messages_.push_back(msg);

	listLock_.unlock();
	workerSemaphore_.up();
}

// --------------------------------

void sender :: clear(void)
{
    listLock_.lock();

    for (std :: list<char*> :: iterator iter = messages_.begin(); iter != messages_.end(); iter++)
        delete *iter;
    messages_.clear();

	listLock_.unlock();
}

// --------------------------------

void sender :: operator ()(threads::thread *thd)
{
	while (true)
	{
		// cekame na zpravu pomoci semaforu
		workerSemaphore_.down();

		// vyjmeme zpravu z fronty
		listLock_.lock();

		char* msg = messages_.front();
		messages_.pop_front();

		listLock_.unlock();

		// jestlize jsme dorazili nakonec, vrat null, jinak posli zpravu
		if (msg == NULL)
			break;

		// posli zpravu
		char* toSend = msg;
		int msgLength = (int)strlen(toSend);
		while (msgLength > 0)
		{
			try
			{
				// zkus poslat zpravu
				int sended = cs_->sendData(toSend, msgLength);
				msgLength -= sended;
				toSend += sended;
			}
			catch (std :: exception e)
			{
				// vyjimka, pouze prerus cyklus
				break;
			}
		}

		// smaz zpravu
		delete msg;
	}
}

// --------------------------------
// --------------------------------

void receiver :: operator()(threads :: thread* thd)
{    
    while (true)
    {
		char* msg;

		if (!getMessage(&msg)) {
			break;
		}

        protocolReader r;
        message* m = r.translateMessage(msg);
        delete msg;

        // if message was sucesfully translated, invoke hook
        if (m != NULL)
        {
            hk_->acceptMessage(m);
        }
        else
        {
            hk_->badMessageReceived();
        }
    }

    // error or ending occured, close connection
    try
    {
        cs_->close();
    }
    catch (std :: exception e)
    {
        // nic nedelej
    }
    hk_->connectionClosed();
}

// --------------------------------

#define MAX_MESSAGE_LENGTH 65536
bool receiver :: getMessage(char** result)
{
    *result = NULL;
	int length = 0;
	try
	{
		// nacteme ze socketu pocet znaku v nasledujici zprave
		std :: string len = "";

		while (true)
		{
			char c;
			if (cs_->recvData(&c, 1) > 0)
			{
				if (isdigit(c))
				{
					len += c;
				}
				else break;
			}
			else
			{
				return false;
			}
		}

		length = atoi(len.c_str());
	}
	catch (std :: exception e)
	{
		return false;
	}

	// zkontrolujeme, jestli zprava neni prilis velka
	if (length > MAX_MESSAGE_LENGTH || length <= 0)
	{
		return false;
	}

	// naalokujeme buffer pro zpravu
	char* msg = NULL;
	try
	{
		msg = new char[length + 1];
	}
	catch (std :: bad_alloc e)
	{
		return false;
	}

	// nacteme zpravu
	try
	{
		for (int i = 0; i < length; i++) 
		{
			char c;
			if (cs_->recvData(&c, 1) > 0)
			{
				msg[i] = c;
			}
			else
			{
				delete msg;
				return false;
			}
		}
	}
	catch (std :: exception e)
	{
		delete msg;
		return false;
	}
	msg[length] = 0;

	// nastavime zpravu
	*result = msg;

	return true;
}


// --------------------------------
// --------------------------------

// --------------------------------
