/*************************************************************************************************************
This file contains start/stop server function
2012/6 by Dlxko
**************************************************************************************************************/
#include "ServerStartEnd.h"

// Winsock data
static WSADATA wsaData;

// Results
static int result;
static int i;

// For non-blocking
static unsigned long b = 1;

/*********************** START SERVER **************************/
void function_start_server()
{
	// Structures
	server_address.sin_family = AF_INET;
	server_address.sin_addr.s_addr = INADDR_ANY;
	server_address.sin_port = htons ( PORT);

	// Just copy
	memcpy ( &server_socket_address, &server_address, sizeof ( SOCKADDR_IN ) );

	// Start WinSock or report error
	result = WSAStartup (MAKEWORD(1,1), &wsaData);
	if (result == WSASYSNOTREADY)
		function_show_error("WSA Startup: he underlying network subsystem is not ready for network communication.");
	else if (result == WSAVERNOTSUPPORTED)
		function_show_error("WSA Startup: The version of Windows Sockets support requested is not provided by this particular Windows Sockets implementation.");
	else if (result == WSAEINPROGRESS)
		function_show_error("WSA Startup: A blocking Windows Sockets 1.1 operation is in progress.");
	else if (result == WSAEPROCLIM)
		function_show_error("WSA Startup: A limit on the number of tasks supported by the Windows Sockets implementation has been reached.");
	else if (result == WSAEFAULT)
		function_show_error("WSA Startup: The lpWSAData parameter is not a valid pointer.");
	function_show_ready("WSA Startup success!");

	// Create socket or report errors
	server_socket = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
	if (server_socket == INVALID_SOCKET || server_socket == SOCKET_ERROR)
	{
		memset(warnings_tmp, 0, 400);
		sprintf_s(warnings_tmp, 400, "WSA Socket: Failed to create socket with error %d", WSAGetLastError());
		function_show_error(warnings_tmp);
	}
	function_show_ready("WSA Socket success!");

	// Sets the option to re-use the address the entire run of the program
	//setsockopt (server_socket, SOL_SOCKET, SO_REUSEADDR, ( char * ) &i, sizeof ( i ) );

	// Bind the socket to the address
	result = bind ( server_socket, &server_socket_address, sizeof (server_socket_address) );
	if ( result != 0 )
	{
		memset(warnings_tmp, 0, 400);
		sprintf_s(warnings_tmp, 400, "WSA Bind: Failed to bind with error %d", WSAGetLastError());
		function_show_error(warnings_tmp);
	}
	function_show_ready("WSA Bind success!");

	// Start listening for connection requests
	result = listen (server_socket, SOMAXCONN);
	if ( result != 0 )
	{
		memset(warnings_tmp, 0, 400);
		sprintf_s(warnings_tmp, 400, "WSA Listen: Failed to listen with error %d", WSAGetLastError());
		function_show_error(warnings_tmp);
	}
	function_show_ready("WSA Listen success!");

	// This makes the server non blocking, hence it won't wait for a response
	ioctlsocket ( server_socket, FIONBIO, &b );
	function_show_ready("WSA Ioctlsocket set to non-blocking!");

	// Clear all clients state
	for ( int j = 0; j < MAX_CLIENTS; j++ )
	{
		client[j].connected = FALSE;
		memset(&client[j], 0, 10);
	}
	function_show_ready("Clients refreshed!");

	cout << color(FOREGROUND_GREEN|FOREGROUND_GREEN)                                                                                               << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Server port is: "         << color(FOREGROUND_BLUE|FOREGROUND_RED) << PORT                << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Server socket is: "       << color(FOREGROUND_BLUE|FOREGROUND_RED) << server_socket       << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "--------------------------------------"                                                  << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Database ip is: "         << color(FOREGROUND_BLUE|FOREGROUND_RED) << DB_IP               << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Database user is: "       << color(FOREGROUND_BLUE|FOREGROUND_RED) << DB_USER             << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Database pass is: "       << color(FOREGROUND_BLUE|FOREGROUND_RED) << DB_PASS             << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Database name is: "	   << color(FOREGROUND_BLUE|FOREGROUND_RED) << DB_NAME             << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Database port is: "       << color(FOREGROUND_BLUE|FOREGROUND_RED) << DB_PORT             << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "--------------------------------------"                                                  << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Maximum clients is: "     << color(FOREGROUND_BLUE|FOREGROUND_RED) << MAX_CLIENTS         << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Opcode size is: "         << color(FOREGROUND_BLUE|FOREGROUND_RED) << OPCODE_SIZE         << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Code size is: "           << color(FOREGROUND_BLUE|FOREGROUND_RED) << CODE_SIZE           << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Message number size is: " << color(FOREGROUND_BLUE|FOREGROUND_RED) << MSG_NUMB_SIZE       << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Friend data size is: "    << color(FOREGROUND_BLUE|FOREGROUND_RED) << DATA_ONE_SIZE       << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Pass size is: "           << color(FOREGROUND_BLUE|FOREGROUND_RED) << PASS_SIZE           << endl
	 	 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Buffer size is: "         << color(FOREGROUND_BLUE|FOREGROUND_RED) << BUFFER_SIZE         << endl
	 	 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Mysql text size is: "     << color(FOREGROUND_BLUE|FOREGROUND_RED) << MYSQL_TEXT_SIZE     << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "File name size is: "      << color(FOREGROUND_BLUE|FOREGROUND_RED) << FILE_NAME_SIZE      << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "File path size is: "      << color(FOREGROUND_BLUE|FOREGROUND_RED) << FILE_PATH_SIZE      << endl
		 << color(FOREGROUND_GREEN|FOREGROUND_GREEN) << "Lenght size is: "         << color(FOREGROUND_BLUE|FOREGROUND_RED) << LENGHT_SIZE         << endl
		 << white << endl << endl << endl;
}

/*********************** SERVER EXITING *************************/
void function_end_server()
{
	// Disconect all clients
	for ( int j = 0; j < MAX_CLIENTS, j++;) 
	{ 
		function_disconnect_client (&client[j]); 
	}

	// Close server listening socket
	closesocket (server_socket);

	// Clean WinSock2
	WSACleanup();

	//Close MySQL
	mysql_close(&mySQL);

	//Exit 
	cout << endl << endl << color(FOREGROUND_BLUE|FOREGROUND_RED) << "Closing (5 seconds)..." << white << endl;
	Sleep(5000);
	exit(0);
}