#ifndef _PLAYER_H_
#define _PLAYER_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 "GameObject.h"
#include "Position.h"

using namespace TNL;

namespace DinastyOnline {
	namespace Network {

		class GameWorld;
	
		class Player : public GameObject {
			typedef GameObject Parent;
			
		protected:
			TNL::StringTableEntry playerName;
			bool myPlayer;
			Position startPos, endPos;		///< All players move along a line from startPos to endPos.
			TNL::F32 t;                     ///< Parameter of how far the player is along the line from startPos to endPos.
			TNL::F32 tDelta;                ///< Change in t per second (ie, velocity).
	
		public:
	
			/// Player constructor
			Player();
	
			/// Player destructor removes the player from the game.
			//~Player();
			
			StringTableEntry getPlayerName() { return playerName; }
			void setName(const char *string) { playerName = string; };
			
			bool isMyPlayer() { return myPlayer; }
			bool isMoving();
			
			Position getEndPosition() { return endPos; };
			Position getStartPosition() { return startPos; };
			
			/// Mask bits used for determining which object states need to be updated
			/// to all the clients.
			enum MaskBits {
				InitialMask = (1 << 0),  ///< This mask bit is never set explicitly, so it can be used for initialization data.
				PositionMask = (1 << 1), ///< This mask bit is set when the position information changes on the server.
			};
	
			/// performScopeQuery is called to determine which objects are "in scope" for the client
			/// that controls this Player instance.
			void performScopeQuery(TNL::GhostConnection *connection);
	
			/// packUpdate writes the Player's ghost update from the server to the client.
			/// This function takes advantage of the fact that the InitialMask is only ever set
			/// for the first update of the object to send once-only state to the client.
			TNL::U32 packUpdate(TNL::GhostConnection *connection, TNL::U32 updateMask, TNL::BitStream *stream);
	
			/// unpackUpdate reads the data the server wrote in packUpdate from the packet.
			void unpackUpdate(TNL::GhostConnection *connection, TNL::BitStream *stream);
	
			/// serverSetPosition is called on the server when it receives notice from a client
			/// to change the position of the player it controls.  serverSetPosition will call
			/// setMaskBits(PositionMask) to notify the network system that this object has
			/// changed state.
			void serverSetPosition(Position startPos, Position endPos, TNL::F32 t, TNL::F32 tDelta);
	
			/// Move this object along its path.
			///
			/// If it hits the end point, and it's an AI, it will generate a new destination.
			virtual void idle(TNL::F32 timeDelta);
	
			/// onGhostAvailable is called on the server when it knows that this Player has been
			/// constructed on the specified client as a result of being "in scope".
			/// This method call is used to test the per-ghost targeted RPC functionality of
			/// NetObject subclasses by calling rpcPlayerIsInScope on the Player ghost on
			/// the specified connection.
			void onGhostAvailable(TNL::GhostConnection *theConnection);
			
			bool onGhostAdd(TNL::GhostConnection *theConnection);
	
			/// Adds this Player to the list of Player instances in the specified game.
			void addToWorld(GameWorld *theWorld);
	
			/// rpcPlayerWillMove is used to demonstrate ghost->parent NetObject RPCs.
			TNL_DECLARE_RPC(rpcPlayerWillMove,  (TNL::F32 testString));
	
			/// rpcPlayerDidMove is used to demostrate a broadcast RPC from the server
			/// to all of the ghosts on clients scoping this object.  It also demonstrates the
			/// usage of the Float<> template argument, in this case using 6 bits for each X and
			/// Y position.  Float arguments to RPCs are between 0 and 1.
			///TNL_DECLARE_RPC(rpcPlayerDidMove,   (TNL::F32 x, TNL::F32 y));
	
			/// rpcPlayerIsInScope is the RPC method called by onGhostAvailable to demonstrate
			/// targeted NetObject RPCs.  onGhostAvailable uses the TNL_RPC_CONSTRUCT_NETEVENT
			/// macro to construct a NetEvent from the RPC invocation and then posts it only
			/// to the client for which the object just came into scope.
			TNL_DECLARE_RPC(rpcPlayerIsInScope, (TNL::F32 x, TNL::F32 y));
	
			/// This macro invocation declares the Player class to be known
			/// to the TNL class management system.
			TNL_DECLARE_CLASS(Player);
		};
	}
}
#endif
