/*************************************************************************************************************
* This file contains receiving datas function
* 2012/8 by Dlxko
* Version 3.0
**************************************************************************************************************/
#include "RecvData.h"

// Set buffer and bytes counter
static char buffer[BUFFER_SIZE];
static int packet_lenght;
static int bytes_transfered;

// Receiving variables
static float recvmbytes_float;
char recvmbytes_tmp[TEMP_SIZE_MEDIUM];
char recvmbytes_tmp_short[TEMP_SIZE_MEDIUM];
char recvbytes_tmp[TEMP_SIZE_MEDIUM];

// Data stores variables
static char friend_name_buffer[DATA_ONE_SIZE+1];
static char data0[LENGHT_SIZE+1];
static char data2[BUFFER_SIZE];
static char data3[BUFFER_SIZE];
static char data4[BUFFER_SIZE];

// Found buddy variable
static bool buddy_was_found;

// MySql stores
static MYSQL_ROW mysql_row;

// For getting buddy
static int counter;
static int friend_number;
static bool found;

// Additional function to new friend packet (sending feedback packets)
void additional_function_recvdata_new_friend_feedback(int function_type)
{
	// NFR + AUK
	if(function_type != 3)
	{
		// Count lenght
		buffer_text_len = LENGHT_SIZE+CODE_SIZE+OPCODE_SIZE;
		memset(buffer_text_len_char, 0, LENGHT_SIZE);
		sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

		// Update text for server with "DX_OPCODE_NFR" and codes
		memset(buffer_text, 0, BUFFER_SIZE);
		memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_NFR, OPCODE_SIZE);
		if(function_type == 1)
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_AUK, CODE_SIZE);
		else if(function_type == 2)
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_AOK, CODE_SIZE);
		else if(function_type == 4)
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_AWR, CODE_SIZE);

		// Send data
		function_send_data (&client[counter], buffer_text, buffer_text_len);
	}

	// NFD + NAME
	if(function_type == 3)
	{
		buffer_text_len = LENGHT_SIZE + strlen(friend_name_buffer) + OPCODE_SIZE;
		memset(buffer_text_len_char, 0, LENGHT_SIZE);
		sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

		// Update text for server with "DX_OPCODE_NFD" and name datas
		memset(buffer_text, 0, BUFFER_SIZE);
		memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_NFD, OPCODE_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], friend_name_buffer, strlen(friend_name_buffer));

		// Send packet to function_counter client
		function_send_data (&client[counter], buffer_text, buffer_text_len);
	}

	if(function_type == 4)
	{
		// Count lenght
		buffer_text_len = LENGHT_SIZE + strlen(client[counter].nick_name) + OPCODE_SIZE;
		memset(buffer_text_len_char, 0, LENGHT_SIZE);
		sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

		// Update text for server with "DX_OPCODE_NFD" and name datas
		memset(buffer_text, 0, BUFFER_SIZE);
		memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_NFD, OPCODE_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], client[counter].nick_name, strlen(client[counter].nick_name));

		// Send packet to function_counter client
		function_send_data (&client[friend_number], buffer_text, buffer_text_len);
	}
}

// Additional function for registration (sending feedback packets)
void additional_function_recvdata_registration_feedback(int function_type)
{
	// Count lenght
	buffer_text_len = LENGHT_SIZE + CODE_SIZE + OPCODE_SIZE;
	memset(buffer_text_len_char, 0, LENGHT_SIZE);
	sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

	// Update text for server with "DX_OPCODE_REG" and codes
	memset(buffer_text, 0, BUFFER_SIZE);
	memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
	memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_REG, OPCODE_SIZE);
	if (function_type == 1)
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_ROK, CODE_SIZE);
	else if (function_type == 2)
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_RWR, CODE_SIZE);
	else if (function_type == 3)
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_RUK, CODE_SIZE);

	// Send packet
	function_send_data (&client[counter], buffer_text, buffer_text_len);
}

// Additional function for loggining (sending feedback packets)
void additional_function_recvdata_loggining_feedback(int function_type)
{
	// Count lenght and send data
	buffer_text_len = LENGHT_SIZE + OPCODE_SIZE + CODE_SIZE;
	memset(buffer_text_len_char, 0, LENGHT_SIZE);
	sprintf_s(buffer_text_len_char, LENGHT_SIZE, "%d", buffer_text_len);

	// Update text for server with "DX_OPCODE_AUC" and AWR code
	memset(buffer_text, 0, BUFFER_SIZE);
	memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
	memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_AUC, OPCODE_SIZE);
	if (function_type == 1)
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_AWR, CODE_SIZE);
	else if (function_type == 2)
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], DX_CODE_AOK, CODE_SIZE);

	// Send packet
	function_send_data ( &client[counter], buffer_text, buffer_text_len );
}

// Function to delete event
void packet_delete_event()
{
	// Friends name
	memset(data2, 0, BUFFER_SIZE);
	function_midcopy(buffer, data2, (OPCODE_SIZE+LENGHT_SIZE), packet_lenght);

	// Show message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|DEV-%s|->> [%s] wants to remove event [%s]", data0, client[counter].nick_name, data2);
	function_show_info(warnings_tmp);

	// Mark as read
	memset(mysql_text, 0, MYSQL_TEXT_SIZE);
	sprintf_s(mysql_text, "DELETE FROM events WHERE id = %s", data2);
	mysql_return_value = function_mysql_returned(mysql_text);

	// Check returned value
	if(mysql_return_value != NO_RESULT_OR_SUCESS)
		function_show_warning("Can't remove event!");
}

// Function to get history
void packet_get_history()
{
	// Alloc info buffers
	char *day = new char[DATA_ONE_SIZE+1];
	char *month = new char[DATA_ONE_SIZE+1];
	char *year = new char[DATA_ONE_SIZE+1];

	// Day text
	memset(day, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, day, (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE), (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+2));

	// Month text
	memset(month, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, month, (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE+2), (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+4));

	// Year text
	memset(year, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, year, (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE+4), packet_lenght);

	// Show message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|HIS-%s|->> [%s] wants show history [%s:%s:%s]", data0, client[counter].nick_name, day, month, year);
	function_show_info(warnings_tmp);

	// Process
	function_send_history_messages(&client[counter], friend_name_buffer, day, month, year);

	// Deallocate
	delete day, month, year;
}

// Function to process getting info
void packet_get_info()
{
	// Alloc mysql result
	MYSQL_RES *mysql_result = NULL;

	// Show message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|INF-%s|->> [%s] wants show info for [%s]", data0, client[counter].nick_name, friend_name_buffer);
	function_show_info(warnings_tmp);

	// Get result of searching
	memset(mysql_text, 0, MYSQL_TEXT_SIZE);
	sprintf_s(mysql_text, "SELECT * FROM accounts WHERE nickname = '%s'", friend_name_buffer);
	mysql_result = function_mysql_result(mysql_text);

	// Do this while some rows
	while((mysql_row = mysql_fetch_row(mysql_result)))
	{
		// Check data
		if (mysql_row[0] && mysql_row[1] && mysql_row[2] && mysql_row[4] && mysql_row[5] && mysql_row[6] && mysql_row[7])
		{
			// Count lenght
			buffer_text_len = LENGHT_SIZE+OPCODE_SIZE+(DATA_ONE_SIZE*7);
			memset(buffer_text_len_char, 0, LENGHT_SIZE);
			sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

			// Update text for server with "DX_OPCODE_NFR" and AUK code
			memset(buffer_text, 0, BUFFER_SIZE);
			memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_INF, OPCODE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], mysql_row[0], DATA_ONE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE], mysql_row[1], DATA_ONE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+(DATA_ONE_SIZE*2)], mysql_row[2], DATA_ONE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+(DATA_ONE_SIZE*3)], mysql_row[4], DATA_ONE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+(DATA_ONE_SIZE*4)], mysql_row[5], DATA_ONE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+(DATA_ONE_SIZE*5)], mysql_row[6], DATA_ONE_SIZE);
			memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+(DATA_ONE_SIZE*6)], mysql_row[7], DATA_ONE_SIZE);

			// Send packet to requester
			function_send_data (&client[counter], buffer_text, buffer_text_len);
		}
	}

	// Dealloc result if exist
	if (mysql_result)
		mysql_free_result(mysql_result);
}

// Function to process adding new accepted friend
void packet_accept_friend_request()
{
	// Show message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|AFR-%s|->> [%s] wants accept friend [%s]", data0, client[counter].nick_name, friend_name_buffer);
	function_show_info(warnings_tmp);

	// Get friend id
	friend_number = function_get_buddy_number(friend_name_buffer);

	// Insert into database new row with new friend state for this client
	memset(mysql_text, 0, MYSQL_TEXT_SIZE);
	sprintf_s(mysql_text, "INSERT INTO buddylist (client_name, friend_name) VALUES ('%s', '%s');", client[counter].nick_name, friend_name_buffer);
	mysql_return_value = function_mysql_returned(mysql_text);

	// Check returned value
	if(mysql_return_value != NO_RESULT_OR_SUCESS)
		function_show_error("Can't insert client into buddy list after accepting!");

	if(friend_number != MAX_CLIENTS+1)
		function_budies_update(friend_number);

	// Update avivable clients for this one
	function_budies_update(counter);
}

// Function to process adding new friend
void packet_add_new_friend()
{
	// Show message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|NFR-%s|->> [%s] wants to add friend [%s]", data0, client[counter].nick_name, friend_name_buffer);
	function_show_info(warnings_tmp);

	// Get friend id and check it
	friend_number = function_get_buddy_number(friend_name_buffer);

	// Check if already exist in buddy list
	sprintf_s(mysql_text, "SELECT * FROM buddylist WHERE client_name = '%s' AND friend_name = '%s'", client[counter].nick_name, friend_name_buffer);
	mysql_return_value = function_mysql_returned(mysql_text);

	// If already friends
	if (mysql_return_value == MORE_ROWS_OR_SEARCHED)
	{
		// Remove it
		memset(mysql_text, 0, MYSQL_TEXT_SIZE);
		sprintf_s(mysql_text, "DELETE FROM buddylist WHERE client_name = '%s' AND friend_name = '%s'", client[counter].nick_name, friend_name_buffer);
		mysql_return_value = function_mysql_returned(mysql_text);

		// Check returned value
		if(mysql_return_value != NO_RESULT_OR_SUCESS)
		{
			// Show warning
			function_show_warning("Can't remove buddy from buddy list");

			// Send packet with code AUK and no name
			additional_function_recvdata_new_friend_feedback(1);
		}
		else
		{
			// Send packet with code AOK and no name
			// Say "Everything ok with deleting"
			additional_function_recvdata_new_friend_feedback(2);

			// Send packet with NFD opcode and name
			// Say "Delete from your list this buddy"
			additional_function_recvdata_new_friend_feedback(3);

			// If another buddy isnt offline
			if (friend_number != MAX_CLIENTS+1)
			{
				// Send packet with NFD opcode and name
				// Say "You was deleted remove your friend"
				additional_function_recvdata_new_friend_feedback(4);
			}
		}
	}
	else // If no friendstate found
	{
		// Check if exists in accounts
		memset(mysql_text, 0, MYSQL_TEXT_SIZE);
		sprintf_s(mysql_text, "SELECT * FROM accounts WHERE nickname = '%s'", friend_name_buffer);
		mysql_return_value = function_mysql_returned(mysql_text);

		// If exist reply to client
		if(mysql_return_value == MORE_ROWS_OR_SEARCHED)
		{
			// Insert into database new row with new friend state for this client
			memset(mysql_text, 0, MYSQL_TEXT_SIZE);
			sprintf_s(mysql_text, "INSERT INTO buddylist (client_name, friend_name) VALUES ('%s', '%s')", client[counter].nick_name, friend_name_buffer);
			mysql_return_value = function_mysql_returned(mysql_text);

			// Check returned value
			if(mysql_return_value != NO_RESULT_OR_SUCESS)
			{
				// Show warning
				function_show_warning("Can't insert buddy into buddy list");

				// Send packet with code AUK and no name
				// Say "Something went wrong with your adding"
				additional_function_recvdata_new_friend_feedback(1);
			}
			else
			{
				// If another buddy isnt offline
				if (friend_number != MAX_CLIENTS+1)
				{
					// Update buddies for another one
					function_budies_update(friend_number);
				}

				// Check if already friend doesn't have added
				memset(mysql_text, 0, MYSQL_TEXT_SIZE);
				sprintf_s(mysql_text, "SELECT * FROM buddylist WHERE client_name = '%s' AND friend_name = '%s'", friend_name_buffer, client[counter].nick_name);
				mysql_return_value = function_mysql_returned(mysql_text);

				// If they aren't friendstated
				if(mysql_return_value != MORE_ROWS_OR_SEARCHED)
				{
					// Save into database
					memset(mysql_text, 0, MYSQL_TEXT_SIZE);
					sprintf_s(mysql_text, "INSERT INTO events (id, client_name, req_client, opcode) VALUES (NULL, '%s', '%s', 'NFR');", client[counter].nick_name, friend_name_buffer);
					mysql_return_value = function_mysql_returned(mysql_text);

					// Check returned value
					if(mysql_return_value != NO_RESULT_OR_SUCESS)
					{
						// Show warning
						function_show_warning("Can't insert into events");

						// Send packet with code AUK and no name
						// Say "Something went wrong with your adding"
						additional_function_recvdata_new_friend_feedback(1);
					}
					else
					{
						// If found another client
						if (friend_number != MAX_CLIENTS+1)
						{
							// Update his undelivered events
							function_send_offline_messages(&client[friend_number]);
						}
					}
				}
			}

			// Send packet with code AOK and no name
			// Say "Everything ok with your adding"
			additional_function_recvdata_new_friend_feedback(2);

			// Update avivable clients for this one
			function_budies_update(counter);
		}
		// If client doesn't exist in accounts reply it
		else if (mysql_return_value == NO_ROWS_OR_NOTSEARCHED)
		{
			// Send packet with code AWR and no name
			// Say "Client not found in my database"
			additional_function_recvdata_new_friend_feedback(4);
		}
		else // This is probably database error
		{
			// Send packet with code AUK and no name
			// Say "Something went wrong with your adding"
			additional_function_recvdata_new_friend_feedback(1);
		}
	}
}

// Function to process registration
void packet_registration()
{
	// Allocate some variables
	char *reg1 = new char[DATA_ONE_SIZE+1];
	char *reg2 = new char[DATA_ONE_SIZE+1];
	char *reg3 = new char[DATA_ONE_SIZE+1];
	char *reg4 = new char[128+1];
	char *reg5 = new char[DATA_ONE_SIZE+1];
	char *reg6 = new char[DATA_ONE_SIZE+1];
	char *reg7 = new char[DATA_ONE_SIZE+1];
	char *reg8 = new char[DATA_ONE_SIZE+1];
	char *img_reg = new char[AVATAR_SIZE];

	// Get info
	memset(reg1, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg1, (LENGHT_SIZE+OPCODE_SIZE), (OPCODE_SIZE + DATA_ONE_SIZE+LENGHT_SIZE));
	memset(reg2, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg2, (LENGHT_SIZE+OPCODE_SIZE + DATA_ONE_SIZE), (LENGHT_SIZE+OPCODE_SIZE + (DATA_ONE_SIZE*2)) );
	memset(reg3, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg3, (LENGHT_SIZE+OPCODE_SIZE + DATA_ONE_SIZE*2), (LENGHT_SIZE+OPCODE_SIZE + (DATA_ONE_SIZE*3)) );
	memset(reg4, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg4, (LENGHT_SIZE+OPCODE_SIZE + DATA_ONE_SIZE*3), (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*3)) );
	memset(reg5, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg5, (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*3)), (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*4)) );
	memset(reg6, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg6, (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*4)), (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*5)) );
	memset(reg7, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg7, (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*5)), (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*6)) );
	memset(reg8, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, reg8, (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*6)), (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*7)) );
	memset(img_reg, 0, AVATAR_SIZE);
	function_midcopy(buffer, img_reg, (LENGHT_SIZE+OPCODE_SIZE + 128 + (DATA_ONE_SIZE*7)), packet_lenght);

	// This is only for dubug
	int small_counter = 0;
	do
	{
		std::cout << "[" << buffer[small_counter] << "]";
		++small_counter;
	}
	while (small_counter < packet_lenght);
	std::cout << std::endl;

	// Show message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|REG-%s|->> [%s %s] wants to reg [%s]", data0, reg1, reg2, reg3);
	function_show_info(warnings_tmp);

	// Insert new client into database
	memset(mysql_text, 0, MYSQL_TEXT_SIZE);
	sprintf_s(mysql_text, "INSERT INTO accounts VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, img_reg);

	// Process mysql
	mysql_return_value = function_mysql_returned(mysql_text);

	// If everything ok
	if (mysql_return_value == NO_RESULT_OR_SUCESS)
	{
		// Send packet REG with ROK code
		// Say "Everything gone all right"
		additional_function_recvdata_registration_feedback(1);
	}
	// If already exists
	else if (mysql_return_value == NOT_EXECUTET_QUERY)
	{
		// Send packet REG with RWR code
		// Say "Say found in my database"
		additional_function_recvdata_registration_feedback(2);
	}
	// If unknown error
	else
	{
		// Send packet REG with RWR code
		// Say "Some problem found when processing"
		additional_function_recvdata_registration_feedback(3);
	}

	// Deallocate everything
	delete reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8, img_reg;
}

// Function to process received feedback
void packet_process_sent_feedback()
{
	// Chat number
	memset(data2, 0, BUFFER_SIZE);
	function_midcopy(buffer, data2, (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE), packet_lenght);

	// Print message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|SNT-%s|->> [%s] received from [%s] chat [%s]", data0, client[counter].nick_name, friend_name_buffer, data2);
	function_show_info(warnings_tmp);

	// Get friend id
	friend_number = function_get_buddy_number(friend_name_buffer);

	// Count lenght
	buffer_text_len = LENGHT_SIZE+DATA_ONE_SIZE+OPCODE_SIZE+MSG_NUMB_SIZE;
	memset(buffer_text_len_char, 0, LENGHT_SIZE);
	sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

	// Update text for server with "DX_OPCODE_SNT" and name, chatu number datas
	memset(buffer_text,0,BUFFER_SIZE);
	memcpy(buffer_text, buffer_text_len_char, LENGHT_SIZE);
	memcpy(&buffer_text[LENGHT_SIZE], DX_OPCODE_SNT, OPCODE_SIZE);
	memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE], client[counter].nick_name, strlen(client[counter].nick_name));
	memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE], data2, strlen(data2));

	// Send data if found
	if(friend_number != MAX_CLIENTS+1)
		function_send_data ( &client[friend_number], buffer_text, buffer_text_len);
}

// Function to process new message
void packet_process_new_message()
{
	// Chat number
	memset(data2, 0, BUFFER_SIZE);
	function_midcopy(buffer, data2, (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE), (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE));

	// Message
	memset(data3, 0, BUFFER_SIZE);
	function_midcopy(buffer, data3, (OPCODE_SIZE+LENGHT_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE), packet_lenght);

	// Print message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|MSG-%s|->> [%s] send message [%s] in chat [%s]", data0, friend_name_buffer, data3, data2);
	function_show_info(warnings_tmp);

	// Get friend id
	friend_number = function_get_buddy_number(friend_name_buffer);

	// Process away
	if (client[counter].client_away_status == true)
	{
		client[counter].client_away_timeout = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, AWAY_PROCESS_TIME, (GSourceFunc)function_process_away, (gint*)counter, NULL);
		client[counter].client_away_status = false;
		function_buddy_status_update(counter, 1);
	}

	// Message resending to other client only if online
	if(friend_number != MAX_CLIENTS+1)
	{
		// Count lenght
		buffer_text_len = LENGHT_SIZE+DATA_ONE_SIZE+OPCODE_SIZE + strlen(data3) + MSG_NUMB_SIZE;
		memset(buffer_text_len_char, 0, LENGHT_SIZE);
		sprintf_s(buffer_text_len_char,LENGHT_SIZE, "%d", buffer_text_len);

		// Update text for server with "DX_OPCODE_IMS" and name, chat number, message datas
		memset(buffer_text,0,BUFFER_SIZE);
		memcpy(buffer_text,buffer_text_len_char,LENGHT_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE],DX_OPCODE_IMS,OPCODE_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE],client[counter].nick_name,strlen(client[counter].nick_name));
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE], data2, strlen(data2));
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+ MSG_NUMB_SIZE], data3, strlen(data3));

		// Send packet throught socket to client
		function_send_data ( &client[friend_number], buffer_text, buffer_text_len);

		// Save message to the Database
		sprintf_s(mysql_text, "INSERT INTO messages (member_one, member_two, message, time_stamp, member_one_received, member_two_received) VALUES ('%s', '%s', '%s', CURRENT_TIMESTAMP, 1, 1)", client[counter].nick_name, client[friend_number].nick_name, data3);

		// Execute mysql command
		mysql_return_value = function_mysql_returned(mysql_text);

		// Check returned value
		if(mysql_return_value != NO_RESULT_OR_SUCESS)
			function_show_warning("Can't save message for online state");
	}

	// If buddy wasn't found insert to offline messages
	if(friend_number == MAX_CLIENTS+1)
	{
		memset(mysql_text, 0, MYSQL_TEXT_SIZE);
		sprintf_s(mysql_text, "INSERT INTO messages (id, member_one, member_two, message, time_stamp, member_one_received, member_two_received) VALUES (NULL, '%s', '%s', '%s', CURRENT_TIMESTAMP, 1, 0)", client[counter].nick_name, friend_name_buffer, data3);
		mysql_return_value = function_mysql_returned(mysql_text);

		//Check returned value
		if(mysql_return_value != NO_RESULT_OR_SUCESS)
			function_show_warning("Can't save message for offline state");
	}
}

// Function to process online request
void packet_offline_request()
{
	if (strlen(client[counter].nick_name) < 1)
	{
		// Print message
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|OFL-%s|->> Socket [%d] wants to go offline", data0, client[counter].socket);
		function_show_info(warnings_tmp);

		// Disconnect client
		function_disconnect_client(&client[counter]);

		// Update progress bar
		function_update_progress_clients();
	}
	else
	{
		// Print message
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|OFL-%s|->> [%s] wants to go offline", data0, client[counter].nick_name);
		function_show_info(warnings_tmp);

		// Update buddy lists
		function_buddy_status_update(counter, 2);

		// Disconnect client
		function_disconnect_client(&client[counter]);
	}
}

// Function to process file transfer
void packet_file_transfer()
{
	// Get file name
	memset(data2, 0, BUFFER_SIZE);
	function_midcopy(buffer, data2, (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE), (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+FILE_NAME_SIZE+MSG_NUMB_SIZE));

	//Get msg number
	memset(data4, 0, BUFFER_SIZE);
	function_midcopy(buffer, data4, (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE), (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE));

	// Get url
	memset(data3, 0, BUFFER_SIZE);
	function_midcopy(buffer, data3, (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+FILE_NAME_SIZE+MSG_NUMB_SIZE), packet_lenght);

	// Print message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|FLT-%s|->> [%s] sending [%s] for [%s] in chat [%s]", data0, client[counter].nick_name, data2, friend_name_buffer, data4);
	function_show_info(warnings_tmp);

	// Get friend id
	friend_number = function_get_buddy_number(friend_name_buffer);

	if(friend_number != MAX_CLIENTS+1)
	{
		// Count lenght
		buffer_text_len = LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+FILE_NAME_SIZE +MSG_NUMB_SIZE+ strlen(data3);
		memset(buffer_text_len_char, 0, LENGHT_SIZE);
		sprintf_s(buffer_text_len_char, LENGHT_SIZE, "%d", buffer_text_len);

		// Update text for server with "DX_OPCODE_FLT" and name, url, filename datas
		memset(buffer_text,0,BUFFER_SIZE);
		memcpy(buffer_text,buffer_text_len_char,LENGHT_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE],DX_OPCODE_FLT,OPCODE_SIZE);
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE],client[counter].nick_name,strlen(client[counter].nick_name));
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE], data4, strlen(data4));
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+MSG_NUMB_SIZE], data2, strlen(data2));
		memcpy(&buffer_text[LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE+FILE_NAME_SIZE+MSG_NUMB_SIZE], data3, strlen(data3));

		// Send socket for sender and receiver and clean sock info
		function_send_data ( &client[friend_number], buffer_text, buffer_text_len);
	}
}

// Function to process loggining
void packet_loggining()
{
	// Get password
	memset(data2, 0, BUFFER_SIZE);
	function_midcopy(buffer, data2, (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE), packet_lenght);

	// Print message
	memset(warnings_tmp, 0, WARNING_TMP_SIZE);
	sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|AUC-%s|->> [%s] wants loggin", data0, friend_name_buffer);
	function_show_info(warnings_tmp);

	// Check users in database
	memset(mysql_text, 0, MYSQL_TEXT_SIZE);
	sprintf_s(mysql_text, "SELECT * FROM  accounts WHERE nickname = '%s' AND password = '%s'", friend_name_buffer, data2);

	// If wrong dont acess and report
	// Send packet AUC code AWR
	// Say "Error or already exist"
	if (function_mysql_returned(mysql_text) != MORE_ROWS_OR_SEARCHED)
		additional_function_recvdata_loggining_feedback(1);
	else
	{
		// Send packet AUC and code AOK
		// Say "Everything gone OK"
		additional_function_recvdata_loggining_feedback(2);

		// Save it!
		client[counter].client_acess = 1;
		strcpy_s(client[counter].nick_name, DATA_ONE_SIZE, friend_name_buffer);

		// Create and start away counter
		client[counter].client_away_timeout = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, AWAY_PROCESS_TIME, (GSourceFunc)function_process_away, (gint*)counter, NULL);

		// Update buddies
		function_buddy_status_update(counter, 1);
		function_budies_update(counter);
		function_send_offline_messages(&client[counter]);
	}
}

// Function to get packet type
void function_get_packet_type()
{
	if(buffer[5] == 'D' && buffer[6] == 'E' && buffer[7] == 'V' && client[counter].client_acess == 1)
		packet_delete_event();
	else if(buffer[5] == 'H' && buffer[6] == 'I' && buffer[7] == 'S' && client[counter].client_acess == 1)
		packet_get_history();
	else if(buffer[5] == 'I' && buffer[6] == 'N' && buffer[7] == 'F' && client[counter].client_acess == 1)
		packet_get_info();
	else if(buffer[5] == 'N' && buffer[6] == 'A' && buffer[7] == 'R' && client[counter].client_acess == 1)
		packet_accept_friend_request();
	else if(buffer[5] == 'N' && buffer[6] == 'F' && buffer[7] == 'R' && client[counter].client_acess == 1)
		packet_add_new_friend();
	else if(buffer[5] == 'R' && buffer[6] == 'E' && buffer[7] == 'G' && client[counter].client_acess != 1)
		packet_registration();
	else if(buffer[5] == 'S' && buffer[6] == 'N' && buffer[7] == 'T' && client[counter].client_acess == 1)
		packet_process_sent_feedback();
	else if(buffer[5] == 'M' && buffer[6] == 'S' && buffer[7] == 'G' && client[counter].client_acess == 1)
		packet_process_new_message();
	else if (buffer[5] == 'O' && buffer[6] == 'F' && buffer[7] == 'L')
		packet_offline_request();
	else if (buffer[5] == 'F' && buffer[6] == 'L' && buffer[7] == 'T' && client[counter].client_acess == 1)
		packet_file_transfer();
	else if (buffer[5] == 'A' && buffer[6] == 'U' && buffer[7] == 'C' && client[counter].client_acess != 1)
		packet_loggining();
	else if (buffer[5] == 'D' && buffer[6] == 'I' && buffer[7] == 'S' && client[counter].client_acess == 1)
		function_buddy_status_update(counter, 4);
	else if (buffer[5] == 'O' && buffer[6] == 'N' && buffer[7] == 'L' && client[counter].client_acess == 1)
		function_buddy_status_update(counter, 5);
	else
	{
		// Print message
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "|%c%c%c-%s|->> is unknown", buffer[5], buffer[6], buffer[7], data0);
		function_show_info(warnings_tmp);
	}
}

// Function to handle receiving data from client-server socket
gboolean signal_receive_data(GIOChannel *source,  GIOCondition condition, int client_socket)
{
	// Transfer data
	memset(buffer, 0, BUFFER_SIZE);
	bytes_transfered = recv(client_socket, buffer, BUFFER_SIZE, 0);

	// If no bytes return :)
	if (bytes_transfered == 0)
		return true;

	// Get lenght
	memset(data0, 0, LENGHT_SIZE+1);
	function_midcopy(buffer, data0, 0, LENGHT_SIZE);

	// If no lenght return :)
	if (strlen(data0) == 0)
		return true;

	// Get int lengt
	packet_lenght = function_convert_packet_lenght(data0);

	// Calculate bytes
	bytes_received += bytes_transfered;

	// For mega its little more difficult :)
	recvmbytes_float = mbytes_received + ((float)bytes_transfered / 1000000.0f);
	mbytes_received = recvmbytes_float;
	memset(recvmbytes_tmp, 0, TEMP_SIZE_MEDIUM);
	sprintf_s(recvmbytes_tmp, TEMP_SIZE_MEDIUM, "%f", mbytes_received);
	memset(recvmbytes_tmp_short, 0, TEMP_SIZE_MEDIUM);
	memcpy(recvmbytes_tmp_short, recvmbytes_tmp, 3);

	// Update label
	memset(recvbytes_tmp, 0, TEMP_SIZE_MEDIUM);
	sprintf_s(recvbytes_tmp, TEMP_SIZE_MEDIUM, "<b>Received:</b> <span foreground=\"blue\">%s</span> mbytes (<span foreground=\"blue\">%d</span> bytes)", recvmbytes_tmp_short, bytes_received);
	gtk_label_set_markup (GTK_LABEL (server_datalabel2), recvbytes_tmp);

	// Find this client
	counter = RESET;
	found = false;
	do
	{
		if(client[counter].socket == client_socket)
		{
			found = true;
			break;
		}
		else
			++counter;
	}
	while (counter < MAX_CLIENTS);

	// Client is offline but data in front
	if (found == false)
	{
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "Can't find client to receive with sock %d is probably already offline!", client_socket);
		function_show_warning(warnings_tmp);
		return true;
	}

	// Only if connected
	if (!client[counter].connected )
	{
		memset(warnings_tmp, 0, WARNING_TMP_SIZE);
		sprintf_s(warnings_tmp, WARNING_TMP_SIZE, "Client try to access but not connected with sock: %d", client_socket);
		function_show_error(warnings_tmp);
		return true;
	}

	// Get friend name
	memset(friend_name_buffer, 0, DATA_ONE_SIZE);
	function_midcopy(buffer, friend_name_buffer, (OPCODE_SIZE+LENGHT_SIZE), (LENGHT_SIZE+OPCODE_SIZE+DATA_ONE_SIZE));

	// Get packet type
	function_get_packet_type();

	// Return
	return true;
}