
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_Platform_Network.cpp
// Author : Kevin Floyer-Lea
// Date   : 28-Jun-2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "Network/Asura_Network.h"

// Asura header-files...
#include "Debugging/Asura_Logfile.h"
#include "Network/Asura_Message.h"
#if defined(ASURA_SUPPORT_EXTERNAL_NETWORK)
#include "Network/Asura_NetTransport_System.h"
#endif	// defined(ASURA_SUPPORT_EXTERNAL_NETWORK)

// Game header-files...


////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Static variable declarations...
////////////////////////////////////////////////////////////////////////////////

DEBUGVAR bool	dbg_bLogAsuraMessages	= false;


////////////////////////////////////////////////////////////////////////////////
// Private functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Protected functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Public functions...
////////////////////////////////////////////////////////////////////////////////

static inline void LogMessage(const Asura_Message* pxMessage)
{
	if(dbg_bLogAsuraMessages)
	{
		#if ASURA_NETWORK_LOGGING || (!defined ASURA_NO_DEBUG_OUTPUT && !defined NDEBUG)
			const char* szMessage = "?";
		#endif

		#if ASURA_NETWORK_LOGGING
			Asura_Network::GetMsgIDDesc(pxMessage->GetMsgID(), &szMessage);
		#endif

		Asura_OutputToDebugger(("ID: %i (%s)\tSize: %i\tTo: %6i\tFrom: %6i\n", pxMessage->GetMsgID(), szMessage, pxMessage->GetDataSize(), pxMessage->GetToGuid(), pxMessage->GetFromGuid()));
	}
}

// C L A S S   I M P L E M E N T A T I O N S /////////////////////////////////
void Asura_Network::PlatformInitialise(void)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK

	Asura_NetTransport_System::Initialise();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}


void Asura_Network::PlatformShutdown(void)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::Shutdown();

#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}


void Asura_Network::PlatformUpdate(void)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::Update();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_StartGame()
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::StartGame();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_SetServerLANReporting(bool bEnable)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_Assert(IsServer() && IsExternalNetworkActive(), "Attempted to turn on LAN reporting without being server");
	Asura_NetTransport_System::SetServerLANReporting(bEnable);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::PlatformStartClient(const char* szIPAddressToConnectTo)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetAddress xAddress;
	u_short usPort;
	Asura_NetTransport_System::GetAddressFromString(szIPAddressToConnectTo, &xAddress, &usPort);
	if (usPort)
	{
		Asura_NetTransport_System::SetServerPort(usPort);
	}
	Asura_NetTransport_System::StartClient(xAddress);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}


void Asura_Network::PlatformStopClient(void)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::StopClient();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
} 


bool Asura_Network::PlatformStartServer(void)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	bool bSuccess = Asura_NetTransport_System::StartServerAndHostSession(s_bIsPlayingOnInternet);

	return bSuccess;
#else
	return false;
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::PlatformStopServer( void )
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::StopServer();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_SendMessageToServer(const Asura_Message* pxMessage)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	LogMessage(pxMessage);
	Asura_NetTransport_System::SendMessageToServer(pxMessage);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}


void Asura_Network::Platform_SendMessageToAllClients(const Asura_Message* pxMessage)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	LogMessage(pxMessage);
	Asura_NetTransport_System::SendMessageToAllClients(pxMessage);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}


void Asura_Network::Platform_SendMessageToClientMachine(const Asura_Message* pxMessage, int iMachine)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_Assert(iMachine>=0 && iMachine<(int)Asura_Network::GetMaxNumberOfMachines(), "invalid machine");
	LogMessage(pxMessage);
	Asura_NetTransport_System::SendMessageToClient(iMachine, pxMessage);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_LockMessageQueue(void)
{
}


void Asura_Network::Platform_UnlockMessageQueue(void)
{
}


float Asura_Network::Platform_GetLatency(void)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	if (s_bServer) return 0.0f;

	u_int uLatency = Asura_NetTransport_System::GetLatency();
	return static_cast<float>(uLatency)/1000.0f;
#else
	return 0.0f;
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

u_int Asura_Network::Platform_GetLatencyForPlayer(Asura_Guid uPlayerGuid)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_Assert(IsServer(), "not a server, don't know other machine's pings");
	u_int uMachineIndex = GetMachineForPlayer(uPlayerGuid, true);	// include bots
	if ( (uMachineIndex > 0) && (uMachineIndex < GetMaxNumberOfMachines()) )
	{
		return Asura_NetTransport_System::GetLatencyForMachine(uMachineIndex);
	}
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	return 0;
}

void Asura_Network::Platform_GetNetworkBandwidthUsage(u_int& uSend, u_int& uReceive)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::GetNetworkBandwidthUsage(uSend, uReceive);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_GetPeakNetworkBandwidthUsage(u_int& uSend, u_int& uReceive)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::GetPeakNetworkBandwidthUsage(uSend, uReceive);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

float Asura_Network::Platform_GetPacketLossPercent()
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	return Asura_NetTransport_System::GetPacketLossPercent();
#else
	return 0.0f;
#endif 
}

void Asura_Network::Platform_ResetNetworkBandwidthStats()
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::ResetNetworkBandwidthStats();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_SetServerName(const Asura_UnicodeChar* wszServerName)
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::SetServerName(wszServerName);
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}

void Asura_Network::Platform_EndOfFrame(void)
{
#if defined(ASURA_SUPPORT_EXTERNAL_NETWORK)
	Asura_NetTransport_System::EndOfFrame();
#endif // #ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
}


bool Asura_Network::Platform_ClientMessageHandler(const Asura_Message* pxMessage)
{
	return false;
}

bool Asura_Network::Platform_ServerMessageHandler(const Asura_Message* pxMessage)
{
	return false;
}


// (MH - 13.07.2004) when a player is kicked, the player's machine must be removed from 
// the game. Platform_RemoveMachineFromGame should result in the machine being removed
// within the delay time. Allowing some delay for buffered and guaranteed messages to 
// arrive is advisable, e.g. to ensure the player is informed of why he was kicked.
void Asura_Network::Platform_RemoveMachineFromGame( int iMachine, float fDelay )
{
#ifdef ASURA_SUPPORT_EXTERNAL_NETWORK
	Asura_NetTransport_System::CloseConnection( iMachine, fDelay );
#endif
}


/// End of file. ///
