//----------------------------------------------------------------------
// File			: AVP_ServerEntity_Squad_Marine.h
// Created		: 01 / 11 / 07
// Created By	: Gareth Thomas
// Copyright (C) 2007 Rebellion. All Rights Reserved.
//----------------------------------------------------------------------

//----------------------------------------------------------------------
// BEGIN FILE WRAPPER
//----------------------------------------------------------------------
#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif
#ifndef __AVP_SERVERENTITY_SQUAD_MARINE_H__
#define __AVP_SERVERENTITY_SQUAD_MARINE_H__ 1
//----------------------------------------------------------------------
// END FILE WRAPPER
//----------------------------------------------------------------------

//----------------------------------------------------------------------
// INCLUDES
//----------------------------------------------------------------------

#include "Core/Asura_List.h"

#include "Entity/Controller/AVP_ServerEntity_Squad.h"
#include "Entity/Locations/Objective/Marine/AVP_ServerEntity_Objective_Marine.h"

//----------------------------------------------------------------------
// FORWARD DECLARATIONS
//----------------------------------------------------------------------
class Asura_Message;
class AVP_Brain_Squad_Marine;
class AVP_ServerActor_Human;
class AVP_ServerNode_Objective_Marine;
struct Objective;
struct Axon_Knowledge;

//----------------------------------------------------------------------
// AVP_ServerEntity_Squad-Marine
//----------------------------------------------------------------------
class AVP_ServerEntity_Squad_Marine : public AVP_ServerEntity_Squad
{
	typedef AVP_ServerEntity_Squad PARENT;

public:

	enum SquadCombatState
	{
		SQUAD_COMBAT_STATE_NORMAL = 0,
		SQUAD_COMBAT_STATE_STANDGROUND,
		MAX_SQUAD_COMBAT_STATES,
	};

	enum { MAX_SQUAD_MEMBERS = 8 };

	// Entity interface.
	AVP_ServerEntity_Squad_Marine( Asura_Guid uGuid );
	virtual ~AVP_ServerEntity_Squad_Marine( void );

	// Public Virtual Overridden Functions...
	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual bool HandleMessage( const Asura_Message* pxMessage );
	virtual void Update( void );
	virtual bool CanBeSavedToChunk( void ) const									{ return true; }
	virtual bool IsFilledFromChunkBuffer( void ) const								{ return false; }

#ifdef ASURA_TOOLS
	virtual bool CanBeIncludedInTemplate() const { return true; }
	 virtual void ApplyChangesForTemplateInstance( Tools_EntityTemplateInstance* pxInstance );
#endif

	// Public Static Functions...
	static AVP_ServerEntity_Squad_Marine* Create( const Asura_Guid uGuid );
	static AVP_ServerEntity_Squad_Marine* GetDefaultSquad( void )					{ return s_pxDefaultSquad; }
	static Asura_Hashed_List< AVP_ServerEntity_Squad_Marine >* GetList( void )		{ return &s_xList; }
	static AVP_ServerEntity_Squad_Marine* FindEntity( const Asura_Guid uGuid )		{ return ( s_xList.FindEntity( uGuid ) ); }
	static AVP_ServerEntity_Squad_Marine* GetPlayersSquad( void );

	AVP_Brain_Squad_Marine* GetMarineSquadBrain( void ) const;

	// Squad Leader Access Functions...
	Asura_Guid GetSquadLeaderGuid( void )											{ return m_uSquadLeaderGuid; }
	void SetSquadLeader( Asura_Guid uGuid )											{ m_uSquadLeaderGuid = uGuid; }

	// Squad Data Access Functions...
	bool IsSquadSetup( void )														{ return m_bSquadSetup; }
	bool IsPlayersSquad( void )														{ return m_bIsPlayersSquad; }
	void SetIsPlayersSquad( bool bInVal )											{ m_bIsPlayersSquad = bInVal; }
	bool IsAILedPlayersSquad( void )												{ return m_bIsAILedPlayersSquad; }
	void SetIsAILedPlayersSquad( bool bInVal )										{ m_bIsAILedPlayersSquad = bInVal; }
	u_int GetSquadCombatState()														{ return m_uSquadCombatState; }
	void SetSquadCombatState(u_int uState)											{ m_uSquadCombatState = uState; }

	void SetIsRestrictedToCombatZone( bool bVal )									{ m_bIsLimitedToCombatZone = bVal;}
	void SetCombatZoneGPVGuid( Asura_Guid uGuid )									{ m_uCombatZoneGPVGuid = uGuid;}

	bool GetIsRestrictedToCombatZone( void )										{ return m_bIsLimitedToCombatZone;}
	Asura_Guid GetCombatZoneGPVGuid( void )											{ return m_uCombatZoneGPVGuid;}

	bool ShouldIgnoreAlertState( void )												{ return m_bIgnoreAlertState; }
	void SetShouldIgnoreAlertState( bool bVal )										{ m_bIgnoreAlertState = bVal; }

	bool DoesMemberHaveThreat( void )												{ return m_bMemberHasThreat; }
	bool DoesMemberHaveAlertKnowledge( void )										{ return m_bMemberHasAlertKnowledge; }

	// Objective Data Access Functions
	Objective* GetCurrentObjective( void )											{ return m_pxCurrentObjective; }
	Asura_Guid GetCurrentObjectiveGuid( void )										{ return m_pxCurrentObjective->uObjectiveGuid; }
	u_int GetCurrentObjectiveState( void )											{ return m_pxCurrentObjective->uObjectiveState; }

	u_int GetCurrentObjectiveType( void )											{ return m_uCurrentObjectiveType; }
	u_int GetCurrentObjectiveThreatAction( void )									{ return m_uCurrentObjectiveThreatAction; }
	u_int GetCurrentObjectiveMovementMode( void )									{ return m_uCurrentObjectiveMovementMode; }
	
	bool HasObjective( void )														{ return ( m_pxCurrentObjective != NULL ); }
	

	// Public Member Functions...
	virtual void SendMemberDeadEventMessage( void );
	void TargetAquired( Asura_Guid uThreatSpotterGuid, const Axon_Knowledge& xThreat );
	void AlertAquired( Asura_Guid uAlertSpotterGuid, const Axon_Knowledge& xAlert );
	AVP_ServerActor_Human* GetLeaderMarine( void );
	void EffectSquadMorale( u_int eMoraleEffector, Asura_Guid uIgnoreGuid = ASURA_GUID_UNREGISTERED );
	bool RequestAction( Asura_Guid uMemberGuid, Asura_Guid uIgnoreActionGuid = ASURA_GUID_UNREGISTERED );
	void ReleaseActionGuid( Asura_Guid uGuidToRelease );
	void HasCompletedAction( void );
	void MemberIsMovingToObjective( void );
	void MemberHasRequestedAction( void );
	void MemberHasCompletedAction( void );
	
	// These functions are required to correctly transfer over from an older version of the squad.
	bool GetSquadTransferred( void )												{ return m_bSquadTransferred; }
	void SetSquadTransferred( bool bVal )											{ m_bSquadTransferred = bVal; }
	Asura_Guid GetRetoreSquadMemberGuid( u_int uIndex )								{ return m_auSquadMembers[ uIndex ]; }

	void		SetTarget(Asura_Guid uGuid, int iIndex)								{ m_auTargets[ iIndex ] = uGuid; }
	Asura_Guid	GetTarget(int iIndex)												{ return m_auTargets[ iIndex ]; }

	void		ChooseNewSquadLeader( Asura_Guid uOldLeaderGuid );

	bool AllMembersHaveValidRoute( void );

	Asura_Guid GetLeadGuid()			{ return m_uLeadGuid; }
	Asura_Guid GetRearGuardGuid()		{ return m_uRearGuardGuid; }

	static const char**	GetSquadCombatStateNames( void )								{ return s_aszSquadCombatStateNames; }

	bool HasInvestigator( void )			{ return m_bHasInvestigator; }
	void SetHasInvestigator( bool bVal )	{ m_bHasInvestigator = bVal; }

protected:

	void UpdatePositions();

	// Protected Overridden Member Functions...
	virtual void InitialiseFromBlueprint( const Asura_Blueprint& xBlueprint );

	// Protected Member Functions
	void UpdateCentroid( void );
	void ProcessObjective( void );
	void SetupSquad( void );
	void UpdateSquadThreatStatus( void );
	void ProcessObjectiveActions( AVP_ServerNode_Objective_Marine* pxObjectiveNode );
	void SendPerformActionMessage( AVP_ServerActor_Human* pxSquadMember, Asura_Guid uActionGuid );
	void BuildAssignedActionArrays( void );
	void ProcessCurrentObjective( void );
	void ResetCurrentObjective( void );
	void UpdateLeaderIfNeeded( void );
	void GetNumOptionalAndRequiredActionGuids( u_int* uNumRequired, u_int* uNumOptional, bool bConsiderActiveState = true );
	void GetOptionalAndRequiredGuids( Asura_Guid* pxRequired, Asura_Guid* pxOptional );
	Asura_Guid GetActionGuidToAssign( Asura_Guid* pxActions, u_int uNumActions, Asura_Guid uIgnoreActionGuid, bool bIsRequiredAction );
	void AssignAction( Asura_Guid uMemberGuid, Asura_Guid uGuidToAssign, bool bIsRequiredAction, u_int uNumActions );
	bool BuildRandomisedOptionalArray( u_int uNumOptional, Asura_Guid* pxOptionalActions, Asura_Guid* pxRandomOptionals );
	virtual void SendEventMessages( void );

private:
	
	// Protected Member Variables...
	union
	{
		u_int m_uFlags;

		struct 
		{
			u_int	m_bIsPlayersSquad						: 1,		// Flag to indicate if the player is part of this squad
					m_bOldAndUnusedNow1						: 1,		// Used for event messages
					m_bMemberHasThreat						: 1,		// indicates if any squad member has threat information
					m_bMemberHasAlertKnowledge				: 1,		// Indicates if any squad member has alert information
					// Event Flags...
					m_bOldAndUnusedNow2						: 1,
					m_bHasThreatMessageSent					: 1,
					m_bHasAlertMessageSent					: 1,
					m_bIsAILedPlayersSquad					: 1,
					m_bIsLimitedToCombatZone				: 1,
					m_bIgnoreAlertState						: 1,
					m_bHasInvestigator						: 1,
															: 0;
		};
	};

	AVP_Brain_Squad_Marine*					m_pxSquadBrain;										// SquadsBrain unused at the moment
	Asura_List<Objective>*					m_pxObjectiveList;									// Queue of objectives
	Objective*								m_pxCurrentObjective;								// The squads current objective
	Asura_Guid								m_uSquadLeaderGuid;									// The squad leader guid
	float									m_fTimeSinceLastThreat;
	Asura_Guid*								m_pxAssignedRequiredActions;
	Asura_Guid*								m_pxAssignedOptionalActions;
	u_int									m_uNumAssignedRequiredAction;
	u_int									m_uNumAssignedOptionalAction;
	Asura_Guid								m_uLastObjectiveGuid;
	u_int									m_uNumMembersCompletedActions;
	u_int									m_uNumMembersMovingToObjective;
	u_int									m_uNumMembersRequestedactions;
	u_int									m_bHasObjective;										// Flag to say we have a current objective
	Asura_Guid								m_uCombatZoneGPVGuid;
	u_int									m_uSquadCombatState;
	Asura_Guid								m_uLeadGuid;
	Asura_Guid								m_uRearGuardGuid;

	Asura_Guid								m_auTargets[MAX_SQUAD_MEMBERS];

	// These members are required to correctly transfer over from an older version of the squad.
	Asura_Guid								m_auSquadMembers[MAX_SQUAD_MEMBERS];
	bool									m_bSquadTransferred;
	bool									m_bSquadSetup;		// Flag to indicate if the squad has been initialised correctly

	u_int m_uCurrentObjectiveType;
	u_int m_uCurrentObjectiveThreatAction;
	u_int m_uCurrentObjectiveMovementMode;



	// Static Members...
	static AVP_ServerEntity_Squad_Marine*	s_pxDefaultSquad;
	static Asura_Hashed_List< AVP_ServerEntity_Squad_Marine > s_xList;

	static const char*	 s_aszSquadCombatStateNames[ MAX_SQUAD_COMBAT_STATES ];		// Static array of string of the objectives for tools and debug info

	enum { CURRENT_CHUNK_VERSION = 11 };
};

//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////

#endif //__AVP_SERVERENTITY_SQUAD_MARINE_H__
