#ifndef _GAMECONNECTION_H_
#define _GAMECONNECTION_H_

#include "tnl.h"
#include "tnlNetBase.h"
#include "tnlGhostConnection.h"
#include "tnlNetInterface.h"
#include "tnlNetObject.h"
#include "tnlLog.h"
#include "tnlRPC.h"
#include "tnlString.h"

#include "Position.h"


namespace DinastyOnline {
	namespace Network {
		class Player;
		class GameNetInterface;
	
		class GameConnection : public TNL::GhostConnection {
			typedef TNL::GhostConnection Parent;
		private:
			TNL::StringTableEntry mClientName;
			/// The player object associated with this connection in the server
			TNL::SafePtr<Player> myPlayer;
			TNL::StringTableEntry login;
			TNL::StringTableEntry password;
			
		public:
	
			GameConnection();
			GameConnection(TNL::StringTableEntry login, TNL::StringTableEntry password);
			
			TNL::StringTableEntryRef getClientName() { return mClientName; }
			void setClientName(const char *string) { mClientName = string; }
			
			void writeConnectRequest(TNL::BitStream *stream);
			bool readConnectRequest(TNL::BitStream *stream, const char **errorString);
	
			/// onConnectTerminated is called when the connection request to the server
			/// is unable to complete due to server rejection, timeout or other error.
			/// When a TestConnection connect request to a server is terminated, the client's network interface
			/// is notified
			void onConnectTerminated(TNL::NetConnection::TerminationReason reason, const char *rejectionString);
	
			/// onConnectionTerminated is called when an established connection is terminated, whether
			/// from the local or remote hosts explicitly disconnecting, timing out or network error.
			/// When a TestConnection to a server is disconnected, the client's network interface
			/// is notified
			void onConnectionTerminated(TNL::NetConnection::TerminationReason reason, const char *string);
			
			/// onConnectionEstablished is called on both ends of a connection when the connection is established.
			/// On the server this will create a player for this client, and set it as the client's
			/// scope object.  On both sides this will set the proper ghosting behavior for the connection (ie server to client).
			void onConnectionEstablished();
	
			/// isDataToTransmit is called each time the connection is ready to send a packet.  If
			/// the NetConnection subclass has data to send it should return true.  In the case of a simulation,
			/// this should always return true.
			bool isDataToTransmit();
	
			/// Remote function that client calls to set the position of the player on the server.
			TNL_DECLARE_RPC(rpcSetPlayerPos, (TNL::S32 x, TNL::S32 y));
	
			/// Enumeration constant used to specify the size field of Float<> parameters in the rpcGotPlayerPos method.
			enum RPCEnumerationValues {
				PlayerPosReplyBitSize = 6, ///< Size, in bits of the floats the server sends to the client to acknowledge position updates.
			};
	
			/// Remote function the server sends back to the client when it gets a player position.
			/// We only use 6 bits of precision on each float to illustrate the float compression
			/// that's possible using TNL's RPC.  This RPC also sends bool and StringTableEntry data,
			/// as well as showing the use of the TNL_DECLARE_RPC_ENUM macro.
			TNL_DECLARE_RPC(rpcGotPlayerPos, (bool b1, bool b2, TNL::StringTableEntry string, TNL::S32 x, TNL::S32 y));
	
			/// TNL_DECLARE_NETCONNECTION is used to declare that GameConnection is a valid connection class to the
			/// TNL network system.
			TNL_DECLARE_NETCONNECTION(GameConnection);
		};
	}
}

#endif

