//-----------------------------------------------------------------------------
// File			: ToolsAVP_Node_FleePoint.cpp
// Author		: Gareth Thomas
// Created		: 06 / 03 / 08
// Copyright (c) 2007 Rebellion. All rights reserved.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

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

// Header
#include "Entity/Locations/FleePoint/ToolsAVP_Node_FleePoint.h"

// Asura
#include "Camera/Asura_Camera.h"
#include "Mesh/Asura_Mesh_System.h"

// AVP
#include "Entity/Locations/FleePoint/AVP_ServerNode_FleePoint.h"

#include "Entity/Locations/OrientedNode/GamesceneNode/AVP_ServerNode_GS2Node.h"

// Tools
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Render.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Objects/ToolsAVP_Object_Type.h"

//------------------------------------------------------------------------------
// Constants, Defines, Statics and Globals
//------------------------------------------------------------------------------
Asura_Hashed_List<ToolsAVP_Node_FleePoint>				ToolsAVP_Node_FleePoint::s_xList;
ToolsAVP_Node_FleePoint*								ToolsAVP_Node_FleePoint::s_pxSelectedFleePointNode = NULL;
bool													ToolsAVP_Node_FleePoint::s_bChanged = false;

//-----------------------------------------------------------------------------
// Function Implementations
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: Constructor
//-----------------------------------------------------------------------------
ToolsAVP_Node_FleePoint::ToolsAVP_Node_FleePoint(Asura_Entity* pxEntity)
: PARENT(pxEntity)
{
	Type = TOT_Entity_FleePoint;
	SetMesh("ToolsShape_FleePoint");

	m_xActionList.Clear();

	AVP_ServerNode_FleePoint* pxAVPEntity = (AVP_ServerNode_FleePoint*)Entity;

	if ( pxAVPEntity )
	{
		for ( u_int u = 0; u < pxAVPEntity->GetNumFleeActions(); ++u )
		{
			Asura_Guid uGuid = pxAVPEntity->GetFleeActionGuid( u );

			if ( uGuid != ASURA_GUID_UNREGISTERED )
			{
				m_xActionList.Push_Back(uGuid);
			}
		}
	}

	s_xList.AddToList(this);
}

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

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

	Tools_Entity_Data *pxToolsData = CreateToolsDataWithDefaultName("FleePoint", "FleePoint", uGuid);

	if (pxToolsData == NULL)
	{
		Asura_Assert(false, "ToolsAVP_Node_FleePoint::Create() - no tools data");
	}
	else
	{
		AVP_ServerNode_FleePoint* pxServerObject = new AVP_ServerNode_FleePoint(uGuid);

		if (pxServerObject == NULL)
		{
			Asura_Assert(false, "ToolsAVP_Node_FleePoint::Create() - no server object" );
		}
		else
		{
			pxServerObject->ToolsData = pxToolsData;

			ToolsAVP_Node_FleePoint* pxToolsObject = new ToolsAVP_Node_FleePoint(pxServerObject);

			// Create the game specific tools object and select it.
			if (pxToolsObject == NULL)
			{
				Asura_Assert(false, "ToolsAVP_Node_FleePoint::Create() - no tools object");
			}
			else
			{
				Tools_Object_System::SelectObject(pxToolsObject);

				pxToolsObject->Position		= *Asura_Camera::GetPosition();
				pxToolsObject->m_uGuid		= uGuid;

				pxServerObject->SetPosition(pxToolsObject->Position);

				Tools_Timed_Message_System::AddMessage(Tools_Timed_Message_System::COLOUR_INFO, "Created New Flee Point");
				Tools_SaveAsura::SetEntityModified();
			}
		}
	}
}

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

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: CreateAndReturn
//-----------------------------------------------------------------------------
Tools_Object* ToolsAVP_Node_FleePoint::CreateAndReturn(void)
{
	const Asura_Guid uGuid = Asura_Entity_System::GetCreatedByToolsGuid();

	Tools_Entity_Data *pxToolsData = CreateToolsDataWithDefaultName("FleePoint", "FleePoint", uGuid);

	if (pxToolsData == NULL)
	{
		Asura_Assert(false, "ToolsAVP_Node_FleePoint::Create() - no tools data");
	}
	else
	{
		AVP_ServerNode_FleePoint* pxServerObject = new AVP_ServerNode_FleePoint(uGuid);

		if (pxServerObject == NULL)
		{
			Asura_Assert(false, "ToolsAVP_Node_FleePoint::Create() - no server object" );
		}
		else
		{
			pxServerObject->ToolsData = pxToolsData;

			ToolsAVP_Node_FleePoint* pxToolsObject = new ToolsAVP_Node_FleePoint(pxServerObject);

			// Create the game specific tools object and select it.
			if (pxToolsObject == NULL)
			{
				Asura_Assert(false, "ToolsAVP_Node_FleePoint::Create() - no tools object");
			}
			else
			{
				Tools_Object_System::SelectObject(pxToolsObject);

				pxToolsObject->Position		= *Asura_Camera::GetPosition();
				pxToolsObject->m_uGuid		= uGuid;

				pxServerObject->SetPosition(pxToolsObject->Position);

				Tools_Timed_Message_System::AddMessage(Tools_Timed_Message_System::COLOUR_INFO, "Created New Flee Point");
				Tools_SaveAsura::SetEntityModified();
				return pxToolsObject;
			}
		}
	}

	return NULL;
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: Project_Create
//-----------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::Project_Create(void)
{
	ToolsAVP_Node_FleePoint::Create();
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: CreateObjectOfThisType
//-----------------------------------------------------------------------------
Tools_Object* ToolsAVP_Node_FleePoint::CreateObjectOfThisType(void) const
{
	return CreateAndReturn();
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: OnSelection
//-----------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::OnSelection(void)
{
	s_pxSelectedFleePointNode = this;
	PARENT::OnSelection();
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: OnDeselection
//-----------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::OnDeselection(void)
{
	PARENT::OnDeselection();
	s_pxSelectedFleePointNode = NULL;
}

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

	if ( s_bChanged )
	{
		AVP_ServerNode_FleePoint* pxAVPEntity = ( AVP_ServerNode_FleePoint* )Entity;

		if ( pxAVPEntity )
		{
			u_int		uSize = m_xActionList.Size();
			Asura_Guid* pxGuids = new Asura_Guid[ uSize ];
			u_int		uNumDone = 0;

			Asura_ListElt< Asura_Guid >* pxTestElt = m_xActionList.Front();

			while ( pxTestElt != NULL )
			{
				Asura_Guid uGuid = pxTestElt->Data();

				pxGuids[ uNumDone ] = uGuid;
				++uNumDone;

				pxTestElt = pxTestElt->Next();
			}

			pxAVPEntity->SetActionGuids( pxGuids, uSize );

			delete [] pxGuids;
			Tools_SaveAsura::SetEntityModified();

			s_bChanged = false;
		}
	}
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: Update
//-----------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::Update( void )
{
	PARENT::Update();

	// First Required Ones
	Asura_ListElt< Asura_Guid >* pxTestElt = m_xActionList.Front();

	while ( pxTestElt != NULL )
	{
		Asura_Guid uGuid = pxTestElt->Data();

		AVP_ServerNode_GS2Node* pxGS2Node = AVP_ServerNode_GS2Node::FindEntity(uGuid);

		if ( ( !pxGS2Node ) || ( pxGS2Node && pxGS2Node->GetStructureType() != AVP_GS_ST_HUMANOID_FLEE_ACTION ) )
		{
			pxTestElt = pxTestElt->Next();
			m_xActionList.Remove( uGuid );
			s_bChanged = true;
		}
		else
		{
			pxTestElt = pxTestElt->Next();
		}
	}
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: Render
//-----------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::Render( void )
{
	PARENT::Render();

	Asura_ListElt< Asura_Guid >* pxTestElt = m_xActionList.Front();

	while ( pxTestElt != NULL )
	{
		Asura_Guid uGuid = pxTestElt->Data();

		if (uGuid != ASURA_GUID_UNREGISTERED)
		{
			AVP_ServerNode_GS2Node* pxGS2Node = AVP_ServerNode_GS2Node::FindEntity(uGuid);

			if (pxGS2Node)
			{
				Tools_Render::RenderCylinder(pxGS2Node->GetPosition(), Position, 0.025f, 0xff110088, false);
			}
		}

		pxTestElt = pxTestElt->Next();
	}
}

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

	Asura_Dialog* pxDialog;

	pxDialog = new Asura_StringDisplay_Dialog("Flee Action Game Scenes", xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Add Flee Action", xOffset, SelectActionToAdd, &s_bChanged);
	pxDialog->SetHelpText("Allows Selection of a Required Game Scene Node");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Remove Flee Action(s)", xOffset, SelectActionToRemove, &s_bChanged);
	pxDialog->SetHelpText("Allows Selection of a Required Game Scene Node");
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();
}

//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::SelectActionToAdd( void )
{
	if ( !s_pxSelectedFleePointNode ) { return; }

	ToolsAVP_ChooseFleeAction* pxChooseObject = new ToolsAVP_ChooseFleeAction( AVP_GS_ST_HUMANOID_FLEE_ACTION, true, AddAction );
	pxChooseObject->SetAllowMultipleSelection( true );
	Tools_Object_System::ChooseObject("Select The Flee Action Game Scene Node(s)", pxChooseObject);
}

//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::SelectActionToRemove( void )
{
	if ( !s_pxSelectedFleePointNode ) { return; }

	ToolsAVP_ChooseFleeAction* pxChooseObject = new ToolsAVP_ChooseFleeAction( AVP_GS_ST_HUMANOID_FLEE_ACTION, false, RemoveAction );
	pxChooseObject->SetAllowMultipleSelection( true );
	Tools_Object_System::ChooseObject("Select The Flee action Game Scene Node(s)", pxChooseObject);
}

//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::AddAction( Asura_Guid uGuid )
{
	ToolsAVP_Node_FleePoint* pxToolsObject = GetSelectedFleeObject();
	if ( !pxToolsObject ) { return; }
	if ( uGuid == ASURA_GUID_UNREGISTERED ) { return; }

	pxToolsObject->m_xActionList.Push_Back(uGuid);
}

//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void ToolsAVP_Node_FleePoint::RemoveAction( Asura_Guid uGuid )
{
	ToolsAVP_Node_FleePoint* pxToolsObject = GetSelectedFleeObject();
	if ( !pxToolsObject ) { return; }
	if ( uGuid == ASURA_GUID_UNREGISTERED ) { return; }

	pxToolsObject->m_xActionList.Remove(uGuid);
}

//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
bool ToolsAVP_ChooseFleeAction::CanBeSelected(Tools_Object* pxObject)
{
	if (pxObject->Type != TOT_Entity_AVPGS2Node)
	{
		return false;
	}

	AVP_ServerNode_GS2Node* pxNode = AVP_ServerNode_GS2Node::FindEntity( pxObject->GetGuid() );

	if ( ( !pxNode ) || ( pxNode->GetStructureType() != m_iStructureType ) )
	{
		return false;
	}

	ToolsAVP_Node_FleePoint* pxToolsObject = ToolsAVP_Node_FleePoint::GetSelectedFleeObject();

	if ( !pxToolsObject )
	{
		return false;
	}

	if (m_bAdd)
	{
		// Check we haven't already got it added
		if ( pxToolsObject->m_xActionList.Find( pxNode->GetGuid() ) )
		{
			return false;
		}
	}
	else
	{
		// check we have got it added already to remove
		if ( !pxToolsObject->m_xActionList.Find( pxNode->GetGuid() ) )
		{
			return false;
		}
	}
	
	return true;
}

//-----------------------------------------------------------------------------
// ToolsAVP_Node_FleePoint :: IsBaseOrDerivativeOf
//-----------------------------------------------------------------------------
bool ToolsAVP_Node_FleePoint::IsBaseOrDerivativeOf( int iToolsObjectType ) const
{
	if (iToolsObjectType == TOT_Entity_FleePoint)
	{
		return true;
	}

	return PARENT::IsBaseOrDerivativeOf(iToolsObjectType);
}

