#include "MessageSender.h"
#include "misc.h"


TSignalSender::TSignalSender(boost::asio::ip::tcp::socket& socket, int messageType)
	: Socket(socket)
	, MessageType(messageType)
{
}

void TSignalSender::Send()
{
	boost::asio::async_write(Socket, boost::asio::buffer(&MessageType, 4), boost::bind(&TSignalSender::Handle, shared_from_this(), boost::asio::placeholders::error));
	
}

void TSignalSender::Handle(const boost::system::error_code& error)
{
}


TMessageSender::TMessageSender(boost::asio::ip::tcp::socket& socket, int messageType, std::vector<char> messageData)
	: Socket(socket)
	, MessageType(messageType)
	, MessageDataSize(messageData.size())
	, MessageData(messageData)
{
}

void TMessageSender::Send()
{
	boost::asio::async_write(Socket, boost::asio::buffer(&MessageType, 4), boost::bind(&TMessageSender::Handle, shared_from_this(), boost::asio::placeholders::error));
	boost::asio::async_write(Socket, boost::asio::buffer(&MessageDataSize, 4), boost::bind(&TMessageSender::Handle, shared_from_this(), boost::asio::placeholders::error));
	
	if (MessageDataSize > 0)
	{
		boost::asio::async_write(Socket, boost::asio::buffer(&MessageData[0], MessageDataSize), boost::bind(&TMessageSender::Handle, shared_from_this(), boost::asio::placeholders::error));
	}
}

void TMessageSender::Handle(const boost::system::error_code& error)
{
}



std::vector<char> CreateMessage(const TUserInfo& userInfo, std::string message)
{
	int bufferSize = userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.LastName.size() + userInfo.PhoneNumber.size() + 4 + 4 + 4 + 16 + 4 + message.size() + 1;

	std::vector<char> pBuffer;

	pBuffer.resize(bufferSize);

	//reinterpret_cast<int*>(&pBuffer[0])[0] = CONST_SIGNAL_MESSAGE;
	//reinterpret_cast<int*>(&pBuffer[0])[1] = bufferSize - 8;
	reinterpret_cast<int*>(&pBuffer[0])[2] = userInfo.MapState;

    /*
	if (userInfo.Uik != 0)
	{
		reinterpret_cast<float*>(&pBuffer[0])[3] = CONST_90_DEG;
		reinterpret_cast<int*>(&pBuffer[0])[4] = userInfo.Uik;
	}
    else*/
	{
		reinterpret_cast<float*>(&pBuffer[0])[3] = userInfo.PosX;
        reinterpret_cast<float*>(&pBuffer[0])[4] = userInfo.PosY;
	}

	

	pBuffer[20] = static_cast<char>(userInfo.LastName.size());
	
	if (userInfo.LastName.size() != 0)
	{
	memcpy(&pBuffer[21], &userInfo.LastName[0], userInfo.LastName.size());
	}

	pBuffer[20 + userInfo.LastName.size() + 1] = static_cast<char>(userInfo.FirstName.size());

	if (userInfo.FirstName.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + 22], &userInfo.FirstName[0], userInfo.FirstName.size());
	}

	pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + 22] = static_cast<char>(userInfo.MiddleName.size());

	if (userInfo.MiddleName.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + 23], &userInfo.MiddleName[0], userInfo.MiddleName.size());
	}

	pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + 23] = static_cast<char>(userInfo.PhoneNumber.size());

	if (userInfo.PhoneNumber.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + 24], &userInfo.PhoneNumber[0], userInfo.PhoneNumber.size());
	}

	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.PhoneNumber.size() + 24], &userInfo.Uik, 4);

	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.PhoneNumber.size() + 28], &userInfo.Status, 4);

	pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.PhoneNumber.size() + 32] = message.size();

	if (message.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.PhoneNumber.size() + 33], &message[0], message.size());
	}

	pBuffer = std::vector<char>(pBuffer.begin() + 8, pBuffer.end());

	return pBuffer;
}


void DecodeMessage(std::vector<char> msgData, TUserInfo& userInfo, std::string& message)
{

	userInfo.MapState = *(reinterpret_cast<int*>(&msgData[0]));

	userInfo.PosX = *(reinterpret_cast<float*>(&msgData[4]));

	if (userInfo.PosX == CONST_90_DEG)
	{
		userInfo.PosY = 0.f;
		userInfo.Uik = *(reinterpret_cast<int*>(&msgData[8]));
	}
	else
	{
		userInfo.PosY = *(reinterpret_cast<float*>(&msgData[8]));
		userInfo.Uik = 0;
	}

	char lastNameLen = msgData[12];

	std::string lastName(&msgData[13], &msgData[13 + lastNameLen]);

	char firstNameLen = msgData[13 + lastNameLen];

	std::string firstName(&msgData[14 + lastNameLen], &msgData[14 + lastNameLen + firstNameLen]);

	char middleNameLen = msgData[14 + lastNameLen + firstNameLen];

	std::string middleName(&msgData[15 + lastNameLen + firstNameLen], &msgData[15 + lastNameLen + firstNameLen + middleNameLen]);

	char phoneLen = msgData[15 + lastNameLen + firstNameLen + middleNameLen];

	std::string phone(&msgData[16 + lastNameLen + firstNameLen + middleNameLen], &msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen]);

	int uik;
	
	memcpy(&uik, &msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen], 4);

	int status;

	memcpy(&status, &msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen + 4], 4);

	userInfo.LastName = lastName;
	userInfo.FirstName = firstName;
	userInfo.MiddleName = middleName;
	userInfo.PhoneNumber = phone;

	userInfo.Uik = uik;

	userInfo.Status = status;

	char messageLen = msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen + 4 + 4];

	message = std::string(msgData.begin() + (16 + lastNameLen + firstNameLen + middleNameLen + phoneLen + 4 + 4 + 1), msgData.begin() + (16 + lastNameLen + firstNameLen + middleNameLen + phoneLen + 4 + 4 + 1 + messageLen));

}

std::vector<char> CreateKickPlayerSignal(std::string lastName, std::string firstName, std::string middleName)
{
    int bufferSize = lastName.size() + firstName.size() + middleName.size() + 3;

    std::vector<char> pBuffer;

    pBuffer.resize(bufferSize);

    pBuffer[0] = static_cast<char>(lastName.size());

    if (lastName.size() != 0)
    {
    memcpy(&pBuffer[1], &lastName[0], lastName.size());
    }

    pBuffer[lastName.size() + 1] = static_cast<char>(firstName.size());

    if (firstName.size() != 0)
    {
    memcpy(&pBuffer[lastName.size() + 2], &firstName[0], firstName.size());
    }

    pBuffer[lastName.size() + firstName.size() + 2] = static_cast<char>(middleName.size());

    if (middleName.size() != 0)
    {
    memcpy(&pBuffer[lastName.size() + firstName.size() + 3], &middleName[0], middleName.size());
    }

    //pBuffer = std::vector<char>(pBuffer.begin() + 8, pBuffer.end());

    return pBuffer;
}

void DecodeKickPlayerSignal(std::vector<char> msgData, std::string& lastName, std::string& firstName, std::string& middleName)
{
    char lastNameLen = msgData[0];

	if (lastNameLen > 0)
	{
		lastName = std::string(&msgData[1], &msgData[1 + lastNameLen]);
	}
	else
	{
		lastName = "";
	}

    char firstNameLen = msgData[1 + lastNameLen];

	if (firstNameLen > 0)
	{
		firstName = std::string(&msgData[2 + lastNameLen], &msgData[2 + lastNameLen + firstNameLen]);
	}
	else
	{
		firstName = "";
	}

    char middleNameLen = msgData[2 + lastNameLen + firstNameLen];

	if (middleNameLen > 0)
	{
    middleName = std::string(&msgData[3 + lastNameLen + firstNameLen], &msgData[3 + lastNameLen + firstNameLen] + middleNameLen);
	}
	else
	{
		middleName = "";
	}
}


std::vector<char> CreateProfileUpdateQuery(const TUserInfo& userInfo)
{
	int bufferSize = userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.LastName.size() + userInfo.PhoneNumber.size() + 4 + 16 + 4;

	std::vector<char> pBuffer;

	pBuffer.resize(bufferSize);

	reinterpret_cast<int*>(&pBuffer[0])[0] = userInfo.MapState;

    /*if (userInfo.Uik != 0)
	{
		reinterpret_cast<float*>(&pBuffer[0])[1] = CONST_90_DEG;
		reinterpret_cast<int*>(&pBuffer[0])[2] = userInfo.Uik;
	}
    else*/
	{
		reinterpret_cast<float*>(&pBuffer[0])[1] = userInfo.PosX;
		reinterpret_cast<float*>(&pBuffer[0])[2] = userInfo.PosY;
	}

	
	pBuffer[12] = static_cast<char>(userInfo.LastName.size());
	
	if (userInfo.LastName.size() != 0)
	{
	memcpy(&pBuffer[13], &userInfo.LastName[0], userInfo.LastName.size());
	}

	pBuffer[12 + userInfo.LastName.size() + 1] = static_cast<char>(userInfo.FirstName.size());

	if (userInfo.FirstName.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + 14], &userInfo.FirstName[0], userInfo.FirstName.size());
	}

	pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + 14] = static_cast<char>(userInfo.MiddleName.size());

	if (userInfo.MiddleName.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + 15], &userInfo.MiddleName[0], userInfo.MiddleName.size());
	}

	pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + 15] = static_cast<char>(userInfo.PhoneNumber.size());

	if (userInfo.PhoneNumber.size() != 0)
	{
	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + 16], &userInfo.PhoneNumber[0], userInfo.PhoneNumber.size());
	}

	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.PhoneNumber.size() + 16], &userInfo.Uik, 4);

	memcpy(&pBuffer[userInfo.LastName.size() + userInfo.FirstName.size() + userInfo.MiddleName.size() + userInfo.PhoneNumber.size() + 20], &userInfo.Status, 4);

	return pBuffer;
}

void DecodeProfileUpdateQuery(std::vector<char>& msgData, TUserInfo& userInfo)
{
	userInfo.MapState = *(reinterpret_cast<int*>(&msgData[0]));

	userInfo.PosX = *(reinterpret_cast<float*>(&msgData[4]));

    if (userInfo.PosX == CONST_90_DEG)
	{
		userInfo.PosY = 0.f;
		userInfo.Uik = *(reinterpret_cast<int*>(&msgData[8]));
	}
	else
	{
		userInfo.PosY = *(reinterpret_cast<float*>(&msgData[8]));
		userInfo.Uik = 0;
	}

	char lastNameLen = msgData[12];

	std::string lastName(&msgData[13], &msgData[13 + lastNameLen]);

	char firstNameLen = msgData[13 + lastNameLen];

	std::string firstName(&msgData[14 + lastNameLen], &msgData[14 + lastNameLen + firstNameLen]);

	char middleNameLen = msgData[14 + lastNameLen + firstNameLen];

	std::string middleName(&msgData[15 + lastNameLen + firstNameLen], &msgData[15 + lastNameLen + firstNameLen + middleNameLen]);

	char phoneLen = msgData[15 + lastNameLen + firstNameLen + middleNameLen];

	std::string phone(&msgData[16 + lastNameLen + firstNameLen + middleNameLen], &msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen]);

	int uik;
	
	memcpy(&uik, &msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen], 4);

	int status;

	memcpy(&status, &msgData[16 + lastNameLen + firstNameLen + middleNameLen + phoneLen + 4], 4);

	userInfo.LastName = lastName;
	userInfo.FirstName = firstName;
	userInfo.MiddleName = middleName;
	userInfo.PhoneNumber = phone;

	userInfo.Uik = uik;

	userInfo.Status = status;

	int bufferSize = 16 + lastNameLen + firstNameLen + middleNameLen + phoneLen + 4 + 4;

	msgData.erase(msgData.begin(), msgData.begin() + bufferSize);
}



std::vector<char> CreateHeartBeatQuery(const TUserInfo& userInfo)
{
	int bufferSize = 12;

	std::vector<char> pBuffer;

	pBuffer.resize(bufferSize);

	reinterpret_cast<int*>(&pBuffer[0])[0] = userInfo.MapState;

    /*if (userInfo.Uik != 0)
	{
		reinterpret_cast<float*>(&pBuffer[0])[1] = CONST_90_DEG;
		reinterpret_cast<int*>(&pBuffer[0])[2] = userInfo.Uik;
	}
    else*/
	{
		reinterpret_cast<float*>(&pBuffer[0])[1] = userInfo.PosX;
		reinterpret_cast<float*>(&pBuffer[0])[2] = userInfo.PosY;
	}

	return pBuffer;
}

void DecodeHeartBeatQuery(std::vector<char>& msgData, TUserInfo& userInfo)
{
	userInfo.MapState = *(reinterpret_cast<int*>(&msgData[0]));

	userInfo.PosX = *(reinterpret_cast<float*>(&msgData[4]));

	if (userInfo.PosX == CONST_90_DEG)
	{
		userInfo.PosY = 0.f;
		userInfo.Uik = *(reinterpret_cast<int*>(&msgData[8]));
	}
	else
	{
		userInfo.PosY = *(reinterpret_cast<float*>(&msgData[8]));
		//userInfo.Uik = 0;

	}

	msgData.erase(msgData.begin(), msgData.begin() + 12);
}

void DecodeMapUpdateResponce(std::vector<char> msgData, std::vector<TUserInfo>& userInfoArr)
{
	while (msgData.size() >= 12)
	{
		TUserInfo userInfo;

		DecodeHeartBeatQuery(msgData, userInfo);

		userInfoArr.push_back(userInfo);

	}
}

void DecodeAlarmMapUpdateResponce(std::vector<char> msgData, std::vector<TUserInfo>& userInfoArr)
{
	while (msgData.size() > 0)
	{
		TUserInfo userInfo;

		DecodeProfileUpdateQuery(msgData, userInfo);

		userInfoArr.push_back(userInfo);

	}
}
