#include <GameOS\GameOS.hpp>
#include <GameOS\ToolOS.hpp>
#include <memory.h>
#include <string.h>
//
//
//
extern HGOSFONT3D font3d;
extern HGOSFONT3D Font_Arial8;
void __stdcall ExitTestNetworkShell();
void __stdcall DoMainMenuLogic();



typedef struct
{
	DWORD	PlayerID;
	double	LastTimeSent;

	DWORD	PingsSent;
	DWORD	PingsGot;

	DWORD	Times[4];

} PingData;



PingData	DataPing[16];






static void __stdcall DoGameLogic()
{
//
// Check for ESC key (back to main menu)
//
	DWORD KeyPress=gos_GetKey()&255;

	if( KeyPress==27 )
	{
		gos_DeleteFont( Font_Arial8 );
		gos_NetEndGame();
		Environment.TerminateGameEngine=ExitTestNetworkShell;
		Environment.DoGameLogic=DoMainMenuLogic;
		Environment.UpdateRenderers=0;
		Environment.Key_Exit = KEY_ESCAPE;
		return;
	}
//
// Check for packets
//
	NetPacket* Message;
	Message=gos_NetGetMessage();
	while( Message )
	{
		switch (Message->Type)
		{
			case gosNet_Ping:
			{
				for( DWORD t1=0; t1<16; t1++ )
				{
					if( DataPing[t1].PlayerID==Message->FromID )
					{
						DataPing[t1].PingsGot++;
						memcpy( &DataPing[t1].Times[0], Message->pData, 16 );
						break;
					}
				}
			}
			break;

			case gosNet_GameEnded:
			case 100:
			{
				gos_DeleteFont( Font_Arial8 );
				gos_NetEndGame();
				Environment.TerminateGameEngine=ExitTestNetworkShell;
				Environment.DoGameLogic=DoMainMenuLogic;
				Environment.UpdateRenderers=0;
				Environment.Key_Exit = KEY_ESCAPE;
				return;
			}
			break;
		}
		Message=gos_NetGetMessage();
	}
//
// Find new players
//
	for( DWORD t0=0; t0<(DWORD)gos_NetInformation(gos_NumberOfPlayers); t0++ )
	{
		bool found;
		found=0;
		for( DWORD t1=0; t1<16; t1++ )
		{
			if( DataPing[t1].PlayerID==(DWORD)gos_NetInformation(gos_PlayerID,t0) )
			{
				found=1;
			}
		}
		if( !found && (DWORD)gos_NetInformation(gos_MyID)!=(DWORD)gos_NetInformation(gos_PlayerID,t0) )
		{
			for( DWORD t1=0; t1<16; t1++ )
			{
				if( DataPing[t1].PlayerID==0 )
				{
					DataPing[t1].PlayerID=(DWORD)gos_NetInformation(gos_PlayerID,t0);
					DataPing[t1].PingsGot=0;
					DataPing[t1].PingsSent=0;
					DataPing[t1].LastTimeSent=0.0f;
					memset( &DataPing[t1].Times, 0, 16);
					break;
				}
			}
		}
	}	
//
// Any players that have not been sent pings in over a second, send one!
//
	for( t0=0; t0<(DWORD)gos_NetInformation(gos_NumberOfPlayers); t0++ )
	{
		if( DataPing[t0].PlayerID && (gos_GetElapsedTime()-DataPing[t0].LastTimeSent>1.0f) && (DataPing[t0].PlayerID!=(DWORD)gos_NetInformation(gos_MyID)) )
		{
			NetPacket Packet;
			Packet.ToID = DataPing[t0].PlayerID;
			Packet.Type = gosNet_Ping;
			Packet.pData = 0;
			Packet.Length = 0;
			Packet.Flags = 0;
			gos_NetSendMessage(&Packet);
			DataPing[t0].PingsSent++;
			DataPing[t0].LastTimeSent=gos_GetElapsedTime();
		}
	}
}

static void __stdcall UpdateRenderers()
{
	gos_SetupViewport( 0,0,1,0x00000020, 1.0, 0.0, 0.0, 1.0 );
	gos_TextSetRegion( 0, 0, Environment.screenWidth, Environment.screenHeight );

	gos_TextSetAttributes( Font_Arial8, 0xffff0000, -16, 0, 1, 0, 0 );
	gos_TextSetPosition( 50,10 );
	gos_TextDraw( "Test Ping Times" );
	gos_TextSetAttributes( Font_Arial8, 0xffc0c0c0, -8, 0, 1, 0, 0 );
	gos_TextSetPosition( 220,19 );
	gos_TextDraw( "This machine is the server=/color=ffffffff/bold=1%c/color=ffc0c0c0/bold=0, Player name=/color=ffffffff/bold=1%s/color=ffc0c0c0/bold=0", (gos_NetInformation(gos_AmITheServer) ? 'Y' : 'N'), ((char*)gos_NetInformation(gos_PlayerName,(DWORD)gos_NetInformation(gos_PlayerNumber,(DWORD)(gos_NetInformation(gos_MyID))))) );

	gos_TextSetAttributes( Font_Arial8, 0xffffffff, -16, 0, 1, 0, 0 );
	gos_TextSetPosition( 50,40 );
	gos_TextDraw( "Total Players=%d, Time=%f", (DWORD)gos_NetInformation(gos_NumberOfPlayers), gos_GetElapsedTime() );
	gos_TextSetAttributes( Font_Arial8, 0xffffffff, -8, 0, 1, 0, 0 );

	DWORD ScreenY=80;

	for( DWORD t0=0; t0<(DWORD)gos_NetInformation(gos_NumberOfPlayers); t0++ )
	{
		gos_TextSetPosition( 50,ScreenY );

		if( (DWORD)gos_NetInformation(gos_MyID)!=(DWORD)gos_NetInformation(gos_PlayerID,t0) )
		{
			for( DWORD t1=0; t1<16; t1++ )
			{
				if( DataPing[t1].PlayerID==(DWORD)gos_NetInformation(gos_PlayerID,t0 ) )
				{
					gos_TextDraw( "Player=%s        Number Sent=%d, Received=%d       Ping times:    TO=%dms FROM=%dms   \n",(char*)gos_NetInformation(gos_PlayerName,t0),DataPing[t1].PingsSent,DataPing[t1].PingsGot, DataPing[t1].Times[2]-DataPing[t1].Times[0], DataPing[t1].Times[3]-DataPing[t1].Times[1] );
					ScreenY+=20;
				}
			}
		}
	}
}

static void __stdcall TerminateGameEngine()
{
//
// Send 'game finished' packet to everyone
//
	if( gos_NetInformation(gos_AmITheServer) )
	{
		NetPacket Packet;
		memset( &Packet, 0, sizeof(Packet) );
		Packet.ToID = (DWORD)gos_NetInformation(gos_AllID);
		Packet.Type = 100;
		Packet.pData = 0;
		Packet.Flags = 0;
		Packet.Length = 0;
		gos_NetSendMessage( &Packet );
	}
	ExitTestNetworkShell();
	gos_DeleteFont( Font_Arial8 );
}

//
// Decode game specific data (in Test Ping Times, it's just an ASCII string anyway)
//
char* DecodeData1( void* Data )
{
	if( Data )
	{
		return (char*)Data;
	}
	else
	{
		return "";
	}
}




DWORD InitNetworkPingTimes()
{
//
// Setup environment
//
	Environment.NetworkMaxPlayers = 8;
//
// Test game specific data - fill game information with current time / date
//
	strncpy( (char*)Environment.NetGameInfo, gos_FileTimeString( gos_GetTimeDate() ), 15 );
//
// Test game specific data - pointer to a routine to decode data
//
	Environment.DecodeGameInfo=DecodeData1;
//
// Start test
//
	if( !gos_NetStartGame(0) )
	{
		return 1;
	}
//
//
//
	Font_Arial8=gos_LoadFont("arial.ttf");
	memset( &DataPing, 0, sizeof(DataPing) );
	Environment.DoGameLogic=DoGameLogic;
	Environment.UpdateRenderers=UpdateRenderers;
	Environment.TerminateGameEngine=TerminateGameEngine;
	Environment.Key_Exit = 0;
//
//
//
	return 0;
}