// HTNetServer.h: interface for the HTNetServer class.
//
//////////////////////////////////////////////////////////////////////

#pragma once

#define MAX_PLAYERS 8

struct HTN_PLAYER_INFO
{
	long lRefCount;

	DPNID dpnidPlayer;
	int   playerIdx;
	char playerName[MAX_PLAYER_NAME];

	int score;
	int nextModelNum;

	MobileModel model;
	InputStatus_type input;
};

const double DefaultStatusUpdateDelay = 0.1;
//const double DefaultStatusUpdateDelay = 0.333;
//const double DefaultStatusUpdateDelay = 2;

class HTNetServer
{
	public:
		WorldInformation				m_world;
	protected:
		DPNID								m_pids[MAX_PLAYERS];
		CompactInputStatus_type		m_NetInput[MAX_PLAYERS];
		InputStatus_type				m_ConvertedInput[MAX_PLAYERS];
		bool								m_ValidPlayerIdx[MAX_PLAYERS];

		double					m_currentTime;
		double					m_NextStatusUpdateTime[MAX_PLAYERS];
		double					m_StatusUpdateDelay[MAX_PLAYERS];

		HANDLE					m_ServerThread;
		volatile bool			m_QuitThread;
		volatile bool			m_ThreadRunning;

	protected:
		CRITICAL_SECTION		m_csPlayerContext;
		IDirectPlay8Server*	m_pDPServer;
		long						m_nActivePlayers;
		TCHAR						m_sServerName[MAX_PATH];
		DWORD						m_dwPort;
		bool						m_bServerRunning;
		bool						m_bInitialized;

		HRESULT WINAPI DirectPlayerMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );

	protected:
		inline static HRESULT WINAPI StaticDirectPlayerMessageForwarder( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer )
			{	return s_pHTNetServer->DirectPlayerMessageHandler(pvUserContext,dwMessageId,pMsgBuffer);	}
		static class HTNetServer* s_pHTNetServer;

	public:
		void NotifyOfKill(TankObject* killer, TankObject* killee);
		void RelayChatMessage( HTMSG_CHAT_FULL* pMsg);
		void HandleClientCommand(HTMSG_COMMAND_TO_SERVER* cmd);
		GUID GetInstanceGuid();
		DWORD ServerThread();
		HTNetServer();
		~HTNetServer();

		bool Initialize();

		bool StartServer();
		void StopServer();

		void SendCreatePlayerMsg( HTN_PLAYER_INFO* pPlayerInfo, DPNID dpnidTarget );
		void SendWorldStateToNewPlayer( DPNID dpnidPlayer );
		void SendDestroyPlayerMsgToAll( HTN_PLAYER_INFO* pPlayerInfo );
		void SendMovementInformationOfAll( int targetPlayerIdx );
		void SendPlayerStatusUpdateMsg(int playerTargetIdx, int playerInfoIdx);

		void RetrieveNetworkInput( HTMSG_UPDATE_INPUT* pMsgUpdateInput );

		HRESULT AddPlayer( PDPNMSG_CREATE_PLAYER pPlayerInfo );
		void RemovePlayer( PDPNMSG_DESTROY_PLAYER pDestroyPlayerMsg );

		void UpdateInput();

		bool IsServerHosting() { return m_bServerRunning; }
		bool IsServerThreadRunning() { return m_ThreadRunning; }

		void update(float dtime);
};
