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

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

// core
#include "Core/Asura.h"

// header
#include "Entity/Controller/ToolsAVP_Entity_MarineSquad.h"

// asura
#include "Camera/Asura_Camera.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Rendering/Asura_Render.h"

// avp
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/AVP_Entity_EventIDs.h"
#include "Entity/AVP_Messages.h"
#include "Entity/Controller/AVP_ServerEntity_Squad_Marine.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/ToolsAVP_Entity_Human.h"
#include "Entity/Controller/ToolsAVP_Entity_MarineTeam.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ServerActor_Human.h"

// tools
#include "Entity/GamePlayVolume/ToolsAVP_Entity_GamePlayVolume.h"
#include "Entity/Tools_Entity_Data.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Movement/Tools_Movement.h"
#include "Objects/ToolsAVP_Object_Type.h"
#include "Objects/Tools_Object_System.h"
#include "ToolsAVP_ChooseObjects.h"

//----------------------------------------------------------------------
// Statics
//----------------------------------------------------------------------
ToolsAVP_Entity_MarineSquad*					ToolsAVP_Entity_MarineSquad::s_pxToolsMarineSquad				= NULL;
bool											ToolsAVP_Entity_MarineSquad::s_bSquadChanged					= false;
bool											ToolsAVP_Entity_MarineSquad::s_bAILedSquadChanged				= false;
bool											ToolsAVP_Entity_MarineSquad::s_bIngoreAlertStateChanged			= false;
bool											ToolsAVP_Entity_MarineSquad::s_bCombatZoneRestrictionChanged	= false;
Asura_Hashed_List<ToolsAVP_Entity_MarineSquad>	ToolsAVP_Entity_MarineSquad::s_xList;

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: Constructor
//----------------------------------------------------------------------
ToolsAVP_Entity_MarineSquad::ToolsAVP_Entity_MarineSquad(Asura_Entity* pxEntity)
: PARENT(pxEntity)
, m_bIsPlayersSquad( false )
, m_bIsAILedPlayersSquad( false )
, m_bIgnoreAlertState( false )
, m_bRestrictToCombatZone( false )
, m_uCombatzoneGPVGuid( ASURA_GUID_UNREGISTERED )
, m_iSquadCombatState( AVP_ServerEntity_Squad_Marine::SQUAD_COMBAT_STATE_NORMAL )
, m_bCombatStateChanged( false )
{
	m_pxMarineSquad = static_cast< AVP_ServerEntity_Squad_Marine* >(pxEntity);

	Type = TOT_Entity_MarineSquad;

	SetMesh("ToolsShape_MarineSquad");

	m_bIsPlayersSquad					= m_pxMarineSquad->IsPlayersSquad();
	m_bIsAILedPlayersSquad				= m_pxMarineSquad->IsAILedPlayersSquad();
	m_bIgnoreAlertState					= m_pxMarineSquad->ShouldIgnoreAlertState();
	m_bRestrictToCombatZone				= m_pxMarineSquad->GetIsRestrictedToCombatZone();
	m_uCombatzoneGPVGuid				= m_pxMarineSquad->GetCombatZoneGPVGuid();
	m_iSquadCombatState					= (int)m_pxMarineSquad->GetSquadCombatState();

	s_xList.AddToList(this);
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: Deconstructor
//----------------------------------------------------------------------
ToolsAVP_Entity_MarineSquad::~ToolsAVP_Entity_MarineSquad()
{
	s_xList.RemoveFromList(this);
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: HandlesThisMessage
//----------------------------------------------------------------------
bool ToolsAVP_Entity_MarineSquad::HandlesThisMessage( int iMessageID )
{
	switch (iMessageID)
	{
		case AVP_MSGID_MOUNT_LIFT:
		case AVP_MSGID_DISMOUNT_LIFT:
		case AVP_MSGID_ADD_AI_OBJECTIVE:
		case AVP_MSGID_ADD_SQUAD_MEMBER:
		case AVP_MSGID_REMOVE_SQUAD_MEMBER:
		case AVP_MSGID_MERGE_HUMANOID_SQUADS:
		case AVP_MSGID_SPLIT_HUMANOID_SQUAD:
		case ASURA_MSG_AXON_GS2_EXIT_GAMESCENE:
		case AVP_MSGID_SET_SQUAD_ALERT_STATUS_TO_PASSIVE:
		case AVP_MSGID_SET_SQUAD_ALERT_STATUS_TO_ACTIVE:
		case AVP_MSGID_SET_SQUAD_ALERT_STATUS_TO_AGGRESSIVE:
		case AVP_MSGID_CHANGE_MARINE_SQUAD_SETTINGS:
		case AVP_MSGID_ATTACK_SCRIPTED_TARGET:
		case AVP_MSGID_STOP_ATTACKING_SCRIPTED_TARGET:
		case AVP_MSGID_CHANGE_HUMANOID_SQUAD_MOVEMENT_MODE:
		case AVP_MSGID_LOOK_AT_ENTITY:
		case AVP_MSGID_STOP_LOOKING_AT_ENTITY:
		case AVP_MSGID_ALIENQUEEN_ADD_TO_TARGET_LIST:
		case AVP_MSGID_ALIENQUEEN_REMOVE_FROM_TARGET_LIST:
		{
			return true;
		}
	}

	return PARENT::HandlesThisMessage( iMessageID );
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: HandlesThisEvent
//----------------------------------------------------------------------
bool ToolsAVP_Entity_MarineSquad::HandlesThisEvent(int iEventID) const
{
	switch ( iEventID )
	{
		case AVP_ENTITY_EVENT_SQUAD_ALERTED:
		case AVP_ENTITY_EVENT_SQUAD_ENTERING_COMBAT:
		{
			return true;
		}break;

		default:
		{
			return PARENT::HandlesThisEvent(iEventID);
		}break;
	}
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: Create
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::Create()
{
	const Asura_Guid uGuid = Asura_Entity_System::GetCreatedByToolsGuid();

	Tools_Entity_Data* pxToolsData = Tools_Entity_Object::CreateToolsData("Marine Squad");
	if ( !pxToolsData ) { return; }

	AVP_ServerEntity_Squad_Marine* pxGameMarineSquad = AVP_ServerEntity_Squad_Marine::Create(uGuid);
	if ( !pxGameMarineSquad ) { return; }
	pxGameMarineSquad->ToolsData = pxToolsData;

	ToolsAVP_Entity_MarineSquad* pxToolsMarineSquad = new ToolsAVP_Entity_MarineSquad(pxGameMarineSquad);
	if ( !pxToolsMarineSquad ) { return; }

	Tools_Object_System::SelectObject( pxToolsMarineSquad );

	Asura_Vector_3 xCameraForward;
	Asura_Camera::GetForwardVector(xCameraForward);
	pxToolsMarineSquad->Position = *Asura_Camera::GetPosition() + xCameraForward * 2.0f;
	pxToolsMarineSquad->Orientation.Identity();

	Tools_Timed_Message_System::AddMessage(Tools_Timed_Message_System::COLOUR_DEFAULT, "Created New Marine Squad");
	Tools_SaveAsura::SetEntityModified();
}

//------------------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: Project_Create
//------------------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::Project_Create(void)
{
	ToolsAVP_Entity_MarineSquad::Create();
}
/// End of function "ToolsAVP_Entity_AlienSpawnPoint.cpp::".

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: Create
//----------------------------------------------------------------------
Tools_Object* ToolsAVP_Entity_MarineSquad::Create(Asura_Entity* pxEntity)
{
	return new ToolsAVP_Entity_MarineSquad(pxEntity);
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: Update
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::Update(void)
{
	AVP_ServerEntity_Squad_Marine* pxAVPSquad  = (AVP_ServerEntity_Squad_Marine*)Entity;

	// lets fix up the squads!
	if (pxAVPSquad && !pxAVPSquad->GetSquadTransferred())
	{
		for (Asura_Hashed_List_It<AVP_ServerActor_Human> xIt(AVP_ServerActor_Human::GetList()); !xIt.Done(); xIt.Next())
		{
			AVP_ServerActor_Human* pxHuman = xIt.GetCurrent();

			if (pxHuman)
			{
				for (u_int u = 0; u < MAX_SQUAD_MEMBERS; ++u)
				{
					if (pxHuman->GetGuid() == pxAVPSquad->GetRetoreSquadMemberGuid(u))
					{
						pxHuman->SetInitialSquadGuid(GetGuid());
						break;
					}
				}
			}
		}

		pxAVPSquad->SetSquadTransferred(true);
	}

	if (pxAVPSquad)
	{
		if (pxAVPSquad->GetNumSquadMembers() > 0)
		{
			while (pxAVPSquad->GetNumSquadMembers() > 0)
			{
				Asura_Guid uGuid = pxAVPSquad->GetMemberGuid(0);

				pxAVPSquad->RemoveMember(uGuid);
				Tools_SaveAsura::SetEntityModified();
			}
		}
	}

	PARENT::Update();
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: UpdateWhileSelected
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::UpdateWhileSelected(void)
{
	PARENT::UpdateWhileSelected();

	if (s_bAILedSquadChanged)
	{
		AVP_ServerEntity_Squad_Marine* pxAVPEntity = (AVP_ServerEntity_Squad_Marine*)Entity;

		if (pxAVPEntity)
		{
			if (m_bIsAILedPlayersSquad)
			{
				m_bIsPlayersSquad = false;
				pxAVPEntity->SetIsPlayersSquad(m_bIsPlayersSquad);
			}

			pxAVPEntity->SetIsAILedPlayersSquad(m_bIsAILedPlayersSquad);
		}

		DeleteOverlay();
		CreateOverlay();
		s_bAILedSquadChanged = false;
		Tools_SaveAsura::SetEntityModified();
	}

	if (s_bSquadChanged)
	{
		AVP_ServerEntity_Squad_Marine* pxAVPEntity = (AVP_ServerEntity_Squad_Marine*)Entity;

		if (pxAVPEntity)
		{
			if (m_bIsPlayersSquad)
			{
				m_bIsAILedPlayersSquad = false;
				pxAVPEntity->SetIsAILedPlayersSquad(m_bIsAILedPlayersSquad);
			}

			pxAVPEntity->SetIsPlayersSquad(m_bIsPlayersSquad);
		}

		DeleteOverlay();
		CreateOverlay();
		s_bSquadChanged = false;
		Tools_SaveAsura::SetEntityModified();
	}

	if ( s_bCombatZoneRestrictionChanged )
	{
		AVP_ServerEntity_Squad_Marine* pxAVPEntity = (AVP_ServerEntity_Squad_Marine*)Entity;

		if (pxAVPEntity)
		{
			pxAVPEntity->SetIsRestrictedToCombatZone( m_bRestrictToCombatZone );
			pxAVPEntity->SetCombatZoneGPVGuid( m_uCombatzoneGPVGuid );
		}

		DeleteOverlay();
		CreateOverlay();
		s_bCombatZoneRestrictionChanged = false;
		Tools_SaveAsura::SetEntityModified();
	}

	if ( s_bIngoreAlertStateChanged )
	{
		AVP_ServerEntity_Squad_Marine* pxAVPEntity = (AVP_ServerEntity_Squad_Marine*)Entity;

		if (pxAVPEntity)
		{
			pxAVPEntity->SetShouldIgnoreAlertState( m_bIgnoreAlertState );
		}

		DeleteOverlay();
		CreateOverlay();
		s_bIngoreAlertStateChanged = false;
		Tools_SaveAsura::SetEntityModified();
	}

	if ( m_bCombatStateChanged )
	{
		AVP_ServerEntity_Squad_Marine* pxAVPEntity = (AVP_ServerEntity_Squad_Marine*)Entity;

		if (pxAVPEntity)
		{
			pxAVPEntity->SetSquadCombatState( (u_int) m_iSquadCombatState );
		}

		m_bCombatStateChanged = false;
		Tools_SaveAsura::SetEntityModified();
	}
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: render
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::Render(void)
{
	PARENT::Render();
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: OnDeselcetion
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::OnDeselection(void)
{
	PARENT::OnDeselection();
	s_pxToolsMarineSquad = NULL;
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: OnSelection
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::OnSelection(void)
{
	s_pxToolsMarineSquad = this;
	PARENT::OnSelection();
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: AddOverlayControls
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::AddOverlayControls(Asura_Overlay* pxOverlay, Asura_Vector_2& xOffset)
{
	PARENT::AddOverlayControls(pxOverlay, xOffset);

	Asura_Dialog* pxDialog;

	// Player's squad tick box
	pxDialog = new Asura_Tickbox_Dialog("Is Player's Squad", xOffset, &m_bIsPlayersSquad, &s_bSquadChanged);
	pxDialog->SetHelpText("Have this selected to indicate that this is the players squad");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	// Player's squad tick box
	pxDialog = new Asura_Tickbox_Dialog("Is AI Led Player's Squad", xOffset, &m_bIsAILedPlayersSquad, &s_bAILedSquadChanged);
	pxDialog->SetHelpText("Have this selected to indicate that this is a players squad being led by an AI Actor");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	// Ignore alert state
	pxDialog = new Asura_Tickbox_Dialog("Ignore Alert State", xOffset, &m_bIgnoreAlertState, &s_bIngoreAlertStateChanged);
	pxDialog->SetHelpText("have this set to have the squad ignore alert state when performing objectives, action etc...");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	// Combat Zone Restriction Tick Box
	pxDialog = new Asura_Tickbox_Dialog("Restrict to Combat Zone", xOffset, &m_bRestrictToCombatZone, &s_bCombatZoneRestrictionChanged);
	pxDialog->SetHelpText("Select this to restrict the squad to a combat zone.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	// Select Combat Zone
	pxDialog = new Asura_Function_Dialog("Select Combat Zone", xOffset, SelectGPVForCombatZone);
	pxDialog->SetHelpText("Allows Selection of a game play volume to use as a combat zone.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	if ( m_uCombatzoneGPVGuid != ASURA_GUID_UNREGISTERED )
	{
		ToolsAVP_Entity_GamePlayVolume* pxGPV = ToolsAVP_Entity_GamePlayVolume::FindEntity( m_uCombatzoneGPVGuid );
		if ( pxGPV ) pxDialog->UpdateLabel( pxGPV->GetName() );
	}
	if ( !m_bRestrictToCombatZone ) pxDialog->SetEnabled( false );

	pxDialog = new Asura_Function_Dialog("Clear Selected Combat Zone Game Play Volume", xOffset, ClearCombatZoneGPV);
	pxDialog->SetHelpText("Clears the selected Combat Zone Game Play Volume");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	if ( !m_bRestrictToCombatZone || m_uCombatzoneGPVGuid == ASURA_GUID_UNREGISTERED )	pxDialog->SetEnabled( false );

	// focus on GPV
	pxDialog = new Asura_Function_Dialog("Edit and Focus on Combat Zone Game Play Volume", xOffset, SelectCombatZoneGPV);
	pxDialog->SetHelpText("Moves the camera to the Game Play Volume marked as Combat Zone.");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();
	if ( !m_bRestrictToCombatZone || m_uCombatzoneGPVGuid == ASURA_GUID_UNREGISTERED )	pxDialog->SetEnabled( false );

	pxDialog = new Asura_StringDisplay_Dialog("Select The Squads Combat Type:", xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_DropDown_List_Dialog( xOffset, AVP_ServerEntity_Squad_Marine::GetSquadCombatStateNames(), &m_iSquadCombatState, AVP_ServerEntity_Squad_Marine::MAX_SQUAD_COMBAT_STATES, AVP_ServerEntity_Squad_Marine::MAX_SQUAD_COMBAT_STATES, NULL, &m_bCombatStateChanged);
	pxDialog->SetHelpText("The Squads Current Combat State");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();
	
	// Edit and focus marine team
	pxDialog = new Asura_Function_Dialog( "Edit And Focus On Marine Team", xOffset, SelectMarineTeam);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: ClearCombatZoneGPV
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::ClearCombatZoneGPV( void )
{
	if (s_pxToolsMarineSquad)
	{
		s_pxToolsMarineSquad->m_uCombatzoneGPVGuid = ASURA_GUID_UNREGISTERED;
		s_bCombatZoneRestrictionChanged = true;
	}
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: SelectCombatZoneGPV
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::SelectCombatZoneGPV( void )
{
	ToolsAVP_Entity_GamePlayVolume* pxCombatZoneGPV = ToolsAVP_Entity_GamePlayVolume::FindEntity( s_pxToolsMarineSquad->m_uCombatzoneGPVGuid );

	if (pxCombatZoneGPV)
	{
		Asura_Vector_3		xNewCameraPos	= pxCombatZoneGPV->Position;
		Asura_Matrix_3x3	xNewCameraOri	= *Asura_Camera::GetOrientation();
		Asura_Vector_3		xFwdVec;

		Asura_Camera::GetForwardVector(xFwdVec);
		xNewCameraPos -= xFwdVec * 8.0f;

		Tools_Movement::TeleportCameraToPosition(&xNewCameraPos, &xNewCameraOri);

		Tools_Object_System::SelectObject(ToolsAVP_Entity_MarineTeam::GetInstance());
	}
	else
	{
		Tools_Timed_Message_System::AddMessage(0xff0000, "Combat Zone Game Play Volume does not Exist");
	}
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: SelectGPVForCombatZone
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::SelectGPVForCombatZone( void )
{
	ToolsAVP_ChooseObject_ByType* pxChooseObject = new ToolsAVP_ChooseObject_ByType(TOT_Entity_GamePlayVolume, SetCombatZoneGPVGuid);
	Tools_Object_System::ChooseObject("Pick the Objective point.", pxChooseObject);
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: SetCombatZoneGPVGuid
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::SetCombatZoneGPVGuid( Asura_Guid uGuid )
{
	if ( s_pxToolsMarineSquad )
	{
		s_pxToolsMarineSquad->m_uCombatzoneGPVGuid = uGuid;
		s_bCombatZoneRestrictionChanged = true;
	}
}

//----------------------------------------------------------------------
// ToolsAVP_Entity_MarineSquad :: SelectMarineTeam
//----------------------------------------------------------------------
void ToolsAVP_Entity_MarineSquad::SelectMarineTeam( void )
{
	ToolsAVP_Entity_MarineTeam* pxMarineTeam = ToolsAVP_Entity_MarineTeam::GetInstance();

	if (pxMarineTeam)
	{
		Asura_Vector_3		xNewCameraPos	= pxMarineTeam->Position;
		Asura_Matrix_3x3	xNewCameraOri	= *Asura_Camera::GetOrientation();
		Asura_Vector_3		xFwdVec;

		Asura_Camera::GetForwardVector(xFwdVec);
		xNewCameraPos -= xFwdVec * 8.0f;

		Tools_Movement::TeleportCameraToPosition(&xNewCameraPos, &xNewCameraOri);

		Tools_Object_System::SelectObject(ToolsAVP_Entity_MarineTeam::GetInstance());
	}
	else
	{
		Tools_Timed_Message_System::AddMessage(0xff0000, "Marine Team Not Created");
	}
}
