//////////////////////////////////////////////////////////////////////////////
//
// AVP_ServerEntity_PlayerInfo.h
//
// Copyright (c) 2007 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___AVP_SERVERENTITY_PLAYERINFO_H___
#define ___AVP_SERVERENTITY_PLAYERINFO_H___ 1

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

// Engine independent.
#include "Entity/Asura_Entity.h"

// Project independent
#include "Core/AVP_Settings.h"
#include "Entity/PlayerInfo/AVP_Player_AudioDiary.h"
#include "Entity/PlayerInfo/AVP_Player_Quest.h"
#include "Multiplayer/AVP_Multiplayer_PlayerScore.h"
#include "Core/AVP_Navigation.h"

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class AVP_Multiplayer_KillCounter; 
class AVP_Message_PlayerInfo_ClientUpdate;
class AVP_Message_PlayerInfo_ClientCreate;
class AVP_ServerEntity_Actor;

// C L A S S E S /////////////////////////////////////////////////////////////

class AVP_ServerEntity_PlayerInfo : public Asura_Entity_Server
{
	typedef Asura_Entity_Server PARENT;

public:

	// Pickup intelligent amount info
	enum
	{
		INTELLIGENT_AMOUNT_SCARCE,
		INTELLIGENT_AMOUNT_MEDIUM,
		INTELLIGENT_AMOUNT_PLENTY
	};

	AVP_ServerEntity_PlayerInfo(Asura_Guid uGuid);
	virtual ~AVP_ServerEntity_PlayerInfo();

	virtual bool HandleMessage(const Asura_Message* pxMessage);

	// This function sets the actor guid here, and also ensures the appropriate MakePlayer (and equivalent unset of predecessor actor) is called.
	void SetPuppetGuid(Asura_Guid uGuid);
	Asura_Guid GetPuppetGuid(void) const { return m_uPuppetGuid; }

	// Get the player current species, basically the species of the puppet this player is controlling
	AVP_Settings::Species GetPuppetSpecies() const; 

	// Sets the player guid of the player persecuting us
	void SetPersecutorGuid(Asura_Guid uGuid)	{ m_uPersecutorGuid = uGuid; } 
	Asura_Guid GetPersecutorGuid(void) const	{ return m_uPersecutorGuid; }

	// This funtion set the team for multiplayer team based matches
	void SetMultiplayerTeam(AVP_Settings::Team eMultiplayerTeam);  
	AVP_Settings::Team GetMultiplayerTeam(void) const { return m_eMultiplayerTeam; }

	// Role for hunter / prey type of games
	void SetMultiplayerRole(AVP_Settings::Role eMultiplayerRole)		{ m_eMultiplayerRole = eMultiplayerRole; }
	AVP_Settings::Role GetMultiplayerRole(void) const					{ return m_eMultiplayerRole; }

	// Multiplayer score accesor
	const AVP_Multiplayer_PlayerScore&	GetPlayerScore(void) const		{ return m_xPlayerScore; }
	AVP_Multiplayer_PlayerScore&		GetPlayerScore(void)			{ return m_xPlayerScore; }

	// Intelligent pickup amount accesor
	int	GetIntelligentAmount () const		{ return m_iIntelligentAmount; }

    // Get Quest/Audio diaries
	const AVP_Player_Quest&                        GetQuest() const { return m_xQuest;}
	void										   SetQuest(const AVP_Player_Quest& xQuest) { m_xQuest = xQuest;}
	const Asura_LinkList< AVP_Player_AudioDiary >& GetAudioDiariesList() const { return m_xAudioDiariesList; }
	Asura_LinkList< AVP_Player_AudioDiary >&       GetAudioDiariesList()       { return m_xAudioDiariesList; }
	AVP_Player_AudioDiary*                         GetAudioDiary( u_int uIndex );

	// Kill counter list
	const Asura_Hashed_List<AVP_Multiplayer_KillCounter>&	GetKillCounterList(void) const		{ return m_xKillCounterList; }
	Asura_Hashed_List<AVP_Multiplayer_KillCounter>&			GetKillCounterList(void)			{ return m_xKillCounterList; }
	
	void DestroyKillCounterList(void); 

	// Reset all muliplayer info stored within the players
	static	void						ResetMultiplayerInfoForAllPlayers(void); 

	virtual void MakeClientUpdateMessage();
	virtual bool CanBeSavedToChunk() const { return true; }
	virtual bool IsFilledFromChunkBuffer() const { return false; }
	virtual void WriteToChunkStream(Asura_Chunk_Stream& xStream) const;
	virtual void ReadFromChunkStream(Asura_Chunk_Stream& xStream);
	virtual void PostLoadInitialise();
	virtual void Update();

	const Asura_Vector_3& GetPlayerPosition() const;
	const Asura_Matrix_3x3& GetPlayerOrientation() const;
	Asura_Guid GetPlayerGamePlayVolumeGuid() const { return m_uPlayerGamePlayVolumeGuid; }

	virtual bool GetHasCreateMessage() const { return true; }
	virtual void MakeCreateMessage(Asura_Guid uRequestingClient, bool bSendGuaranteed = false);

	Asura_Guid	GetCheckPointGuid()	const			{ return m_uCheckpointGuid; }
	void		SetCheckPointGuid(Asura_Guid uGuid)	{ m_uCheckpointGuid = uGuid; }

	// Returns whether it calculated anything or not.
	static bool CalculatePlayersCentroid( Asura_Vector_3& xCentroid );
	static bool IsVisibleByAnyPlayer( const Asura_Vector_3& xPosition );

	static AVP_ServerEntity_PlayerInfo* Create(Asura_Guid uGuid);
	static void CreateFromChunkStream(Asura_Guid uGuid, Asura_Chunk_Stream& xStream);

	static AVP_ServerEntity_PlayerInfo* FindEntity(Asura_Guid uGuid) { return s_xList.FindEntity(uGuid); }
	static const Asura_Hashed_List<AVP_ServerEntity_PlayerInfo>* GetList() { return &s_xList; }

	const AVP_Navigation::NavData& GetAINavData()							const { return m_xAIObjectiveNavData; }
	const AVP_Navigation::NavData& GetPlayerNavData()						const { return m_xPlayerObjectiveNavData; }

	const Asura_Vector_3& GetCurrentDirectionToPrimaryObjective()	const { return m_xCurrentDirectionToObjective; }

	float GetCurrentAIRouteDistance( void ) const { return m_fCurrentAIRouteDistance; }

	bool HasPlayerArrivedAtCurrentAIObjective( void ) const { return m_bWeHaveArrivedAtAIObjective; }

	void InitialiseMissionTime( AVP_Settings::Species eSpecies );

private:

	void UpdateAIObjectiveRoute( void );
	void UpdateMissionTime( void );
	void UpdatePlayerObjectiveRoute( void );
	void EstablishNavData( void );

	void FillUpdateData(AVP_Message_PlayerInfo_ClientUpdate& xData) const;
	void FillCreateData(AVP_Message_PlayerInfo_ClientCreate& xData) const;

	Asura_Guid						m_uPuppetGuid;

	Asura_Guid						m_uCheckpointGuid;
	Asura_Guid						m_uPlayerGamePlayVolumeGuid;

	Asura_Guid						m_uPersecutorGuid;
	int     	                    m_iIntelligentAmount;              // Pickup intelligent amount (Scarce, medium, plenty)
	AVP_Settings::Team				m_eMultiplayerTeam; 
	AVP_Settings::Role				m_eMultiplayerRole; 
	AVP_Multiplayer_PlayerScore		m_xPlayerScore;
	Asura_Hashed_List<AVP_Multiplayer_KillCounter>		m_xKillCounterList; 

	AVP_Player_Quest                       m_xQuest;
	Asura_LinkList <AVP_Player_AudioDiary> m_xAudioDiariesList;

	float							m_fRouteUpdateTimer;
	AVP_Navigation::NavData			m_xAIObjectiveNavData;
	AVP_Navigation::NavData			m_xPlayerObjectiveNavData;
	Asura_Vector_3					m_xAIPositionOnRoute;
	Asura_Vector_3					m_xPlayerPositionOnRoute;
	Asura_Vector_3					m_xCurrentDirectionToObjective;
	float							m_fCurrentAIRouteDistance;
	bool							m_bNavDataEstablished;
	Asura_Guid						m_uLastAIObjectiveGuid;
	bool							m_bWeHaveArrivedAtAIObjective;

	bool							m_bLookingAtTaget;
	Asura_Guid						m_uLookAtTargetGuid;
	Asura_Hash_ID					m_uLookAtTargetMarker;

	int m_iMissionTimeHours;
	int m_iMissionTimeMinutes;
	int m_iMissionTimeSeconds;
	float m_fMissionTimer;

	static u_int s_uCentroidCalcFrame;
	static Asura_Vector_3 s_xCentroid;
	static Asura_Hashed_List<AVP_ServerEntity_PlayerInfo> s_xList;
};

#endif // #ifndef ___AVP_SERVERENTITY_PLAYERINFO_H___
