//////////////////////////////////////////////////////////////////////////////
//
// ToolsAVP_Node_GuardZone.cpp
//
// created by Stuart Perry ( 18.04.07 )
//
// Copyright (c) 2007 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header.
#include "Entity/Locations/GuardZone/ToolsAVP_Node_GuardZone.h"

//Asura
#include "Camera/Asura_Camera.h"
#include "Core/Asura_UserInput.h"
#include "Core/Asura_Timers.h"
#include "Interface/Asura_Dialog.h"
#include "Rendering/Asura_Render.h"

//project
#include "Entity/Locations/OrientedNode/AVP_ServerNode_OrientedNode.h"
#include "Entity/Locations/GuardZone/AVP_ServerNode_GuardZone.h"

//Tools
#include "Entity/Tools_SecondaryEntityFile_System.h"
#include "Entity/Locations/OrientedNode/ToolsAVP_Node_OrientedNode.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Misc/Tools_LOS.h"
#include "Misc/Tools_Render.h"
#include "Objects/ToolsAVP_Object_Type.h"

////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Static variable declarations...
////////////////////////////////////////////////////////////////////////////////

ToolsAVP_Node_GuardZone* ToolsAVP_Node_GuardZone::s_pxAVPToolsGuardZone = NULL;

static const char* g_aszPatrolType[] =
{
	"LOOPING",
	"PING_PONG",
	"RANDOM"
};


//////////////////////////////////////////////////////////////////////////////
//
// ToolsAVP_Node_GuardZone
//
//////////////////////////////////////////////////////////////////////////////

/// End of function 'ToolsAVP_Node_GuardZone::ToolsAVP_Node_GuardZone'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::ToolsAVP_Node_GuardZone
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////

ToolsAVP_Node_GuardZone::ToolsAVP_Node_GuardZone( Asura_Entity* pxEntity )
: PARENT( pxEntity )
, m_bChanged(0)
, m_iPatrolType(0)
, m_uNumPatrolPoints(0)
, m_fDisplayErrorTimer(0.0f)
{
	AVP_ServerNode_GuardZone *pxAVPEntity = (AVP_ServerNode_GuardZone*) pxEntity;

	if (pxAVPEntity)
	{
		m_iPatrolType		= pxAVPEntity->m_iPatrolType;
		m_uNumPatrolPoints	= pxAVPEntity->m_iNumGuardPoints;
	}
}

/// End of function 'ToolsAVP_Node_GuardZone::ToolsAVP_Node_GuardZone'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::~ToolsAVP_Node_GuardZone
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
ToolsAVP_Node_GuardZone::~ToolsAVP_Node_GuardZone()
{
}

/// End of function 'ToolsAVP_Node_GuardZone::~ToolsAVP_Node_GuardZone'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::AddOverlayControls
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::AddOverlayControls( class Asura_Overlay* pxNewOverlay, class Asura_Vector_2& xOffset )
{
	PARENT::AddOverlayControls( pxNewOverlay, xOffset );

	Asura_Dialog* pxNewDialog = NULL;

	//Drop down box for setting the patrol type
	pxNewDialog = new Asura_StringDisplay_Dialog("Patrol Type:", xOffset);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();
	pxNewDialog = new Asura_DropDown_List_Dialog(xOffset, g_aszPatrolType, &m_iPatrolType, AVP_ServerNode_GuardZone::NUM_GUARD_ZONE_PATROL_TYPES, AVP_ServerNode_GuardZone::NUM_GUARD_ZONE_PATROL_TYPES, NULL, &m_bChanged,"");
	pxNewDialog->SetHelpText("Select the Patrol Type for this patrol zone.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();
}
/// End of function 'ToolsAVP_Node_GuardZone::AddOverlayControls'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::OnSelection
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::OnSelection()
{
	PARENT::OnSelection();

	m_bStartedToDisplayError = false;
	m_fDisplayErrorTimer = 0.0f;

	s_pxAVPToolsGuardZone = this;
}
/// End of function 'ToolsAVP_Node_GuardZone::OnSelection'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::OnDeselection
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::OnDeselection()
{
	PARENT::OnDeselection();

	s_pxAVPToolsGuardZone = NULL;
}
/// End of function 'ToolsAVP_Node_GuardZone::OnDeselection'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::Render
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::Render()
{
	PARENT::Render();

	if (this == s_pxAVPToolsGuardZone)
	{
		AVP_ServerNode_GuardZone*		pxAVPEntity				= (AVP_ServerNode_GuardZone*)Entity;
		AVP_ServerNode_OrientedNode*	pxPreviousNode			= NULL;
		u_int							uBestPatrolIndex		= 0xffffffff;
		u_int							uLastPatrolIndex		= 0;
		u_int							uPreviousPatrolIndex	= 0;

		for (u_int u = 0; u < (u_int)pxAVPEntity->GetNumGuardPoints(); ++u)
		{
			AVP_ServerNode_OrientedNode* pxNode = AVP_ServerNode_OrientedNode::FindEntity(pxAVPEntity->GetGuardPointGuid(u));

			if (pxNode)
			{
				if (pxNode->GetPatrolOrder() < uBestPatrolIndex)
				{
					uBestPatrolIndex		= pxNode->GetPatrolOrder();
					pxPreviousNode			= pxNode;
					uPreviousPatrolIndex	= pxNode->GetPatrolOrder();
				}

				if (pxNode->GetPatrolOrder() > uLastPatrolIndex)
				{
					uLastPatrolIndex = pxNode->GetPatrolOrder();
				}
			}
		}
		
		bool						bDone = false;

		while (!bDone)
		{
			AVP_ServerNode_OrientedNode*	pxNextNode				= NULL;
			u_int							uBestNextPatrolIndex	= 0xffffffff;

			for (u_int u = 0; u < (u_int)pxAVPEntity->GetNumGuardPoints(); ++u)
			{
				AVP_ServerNode_OrientedNode* pxNode = AVP_ServerNode_OrientedNode::FindEntity(pxAVPEntity->GetGuardPointGuid(u));

				if (pxNode)
				{
					if ((pxNode->GetPatrolOrder() < uBestNextPatrolIndex) && (pxNode->GetPatrolOrder() > uPreviousPatrolIndex))
					{
						uBestNextPatrolIndex	= pxNode->GetPatrolOrder();
						pxNextNode				= pxNode;
					}
				}
			}

			if (pxPreviousNode && pxNextNode)
			{
				Tools_Render::RenderCylinder(pxPreviousNode->GetPosition(), pxNextNode->GetPosition(), 0.05f, 0xffff0000, false);

				pxPreviousNode			= pxNextNode;
				uPreviousPatrolIndex	= pxNextNode->GetPatrolOrder();

				if (uPreviousPatrolIndex >= uLastPatrolIndex)
				{
					bDone = true;
				}
			}
			else
			{
				bDone = true;
			}
		}
	}
}
/// End of function 'ToolsAVP_Node_GuardZone::Render'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::UpdateWhileSelected
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::UpdateWhileSelected()
{
	PARENT::UpdateWhileSelected();

	AVP_ServerNode_GuardZone *pxAVPEntity = (AVP_ServerNode_GuardZone*)Entity;

	if (m_bChanged)
	{
		pxAVPEntity->m_iPatrolType	= m_iPatrolType;
		m_uNumPatrolPoints			= pxAVPEntity->m_iNumGuardPoints; 
	}

	m_fDisplayErrorTimer += Asura_Timers::GetFrameTime();

	if ((!m_bStartedToDisplayError) || (m_fDisplayErrorTimer > 10.0f))
	{
		for (u_int u = 0; u < m_uNumPatrolPoints; ++u)
		{
			AVP_ServerNode_OrientedNode* pxTestNode = AVP_ServerNode_OrientedNode::FindEntity(pxAVPEntity->m_puGuardPointGuids[u]);

			if (pxTestNode)
			{
				u_int uTestPatrolOrder = pxTestNode->GetPatrolOrder();

				for (u_int v = 0; v < m_uNumPatrolPoints; ++v)
				{
					AVP_ServerNode_OrientedNode* pxNode = AVP_ServerNode_OrientedNode::FindEntity(pxAVPEntity->m_puGuardPointGuids[v]);

					if (pxNode)
					{
						if (pxNode == pxTestNode)
						{
							continue;
						}

						if (uTestPatrolOrder == pxNode->GetPatrolOrder())
						{
							char  acText [128];

							Asura_PrintfToBfr(acText, "Duplicate Patrol Order: %d, Please check patrol points and reorder the duplicate.", 128, true, uTestPatrolOrder);
							Tools_Timed_Message_System::AddMessage(Tools_Timed_Message_System::COLOUR_ERROR, acText);
							m_bStartedToDisplayError = true;
							m_fDisplayErrorTimer = 0.0f;
						}
					}
				}
			}
		}
	}
}
/// End of function 'ToolsAVP_Node_GuardZone::UpdateWhileSelected'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::Project_Create
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::Project_Create()
{
	ToolsAVP_Node_GuardZone::Create();
}
/// End of function 'ToolsAVP_Node_GuardZone::Project_Create'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::Create
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
void ToolsAVP_Node_GuardZone::Create()
{
	ToolsAVP_Node_GuardZone::CreateAndReturn();
}
/// End of function 'ToolsAVP_Node_GuardZone::Create'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::Create
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
Tools_Object* ToolsAVP_Node_GuardZone::Create( Asura_Entity* pxEntity )
{
	return new ToolsAVP_Node_GuardZone( pxEntity );
}
/// End of function 'ToolsAVP_Node_GuardZone::Create'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::CreateAndReturn
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
ToolsAVP_Node_GuardZone* ToolsAVP_Node_GuardZone::CreateAndReturn()
{
	// Get a new GUID
	const Asura_Guid uGuid = Asura_Entity_System::GetCreatedByToolsGuid();

	// Set up tools data and auto-create a unique name (prompt for new name if there is a clash).
	Tools_Entity_Data* pxToolsData = CreateToolsData( "Guard Zone" );
	if ( !pxToolsData ) { return NULL; }

	// Create the game specfic server object and set its data.
	////Asura_ServerNode_GuardZone* pxGameNode = new Asura_ServerNode_GuardZone( uGuid );
	AVP_ServerNode_GuardZone* pxGameNode = new AVP_ServerNode_GuardZone( uGuid );
	if ( !pxGameNode ) { return NULL; }

	pxGameNode->ToolsData = pxToolsData;

	// Create the game specific tools object and select it.
	ToolsAVP_Node_GuardZone* pxToolsNode = new ToolsAVP_Node_GuardZone( pxGameNode );
	if ( !pxToolsNode ) { return NULL; }

	Tools_Object_System::SelectObject( pxToolsNode );

	pxToolsNode->Position = *Asura_Camera::GetPosition();
	pxToolsNode->Orientation = *Asura_Camera::GetOrientation();

	pxGameNode->SetPosition( pxToolsNode->Position );

	Tools_Timed_Message_System::AddMessage( Tools_Timed_Message_System::COLOUR_DEFAULT, "Created new GuardZone" );
	Tools_SaveAsura::SetEntityModified();

	return pxToolsNode;
}
/// End of function 'ToolsAVP_Node_GuardZone::CreateAndReturn'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : ToolsAVP_Node_GuardZone::AddGuardPoint
// Author       : Stuart Perry
// Date         : 18-APRIL-2007
////////////////////////////////////////////////////////////////////////////////
bool ToolsAVP_Node_GuardZone::AddGuardPoint( const Asura_Vector_3& xPosition )
{
	if (s_pxAVPToolsGuardZone != this)
	{
		Asura_Assert(false, "No guard zone selected?");
		return false;
	}

	// Check that the position is within range.
	if ( !IsPositionInsideGuardZone(xPosition))
	{
		Tools_Timed_Message_System::AddMessage(Tools_Timed_Message_System::COLOUR_WARNING, "Point is not inside guard zone");
		return false;
	}

	// This is the only change from the base class
	AVP_ServerNode_GuardZone*		pxGameNode		= AVP_ServerNode_GuardZone::FindEntity(s_pxAVPToolsGuardZone->GetGuid());
	ToolsAVP_Node_OrientedNode*		pxGuardPoint	= NULL;
	
	// Increase the local GuardPoint count ready for the initial addOverlay call for Oriented node
	++m_uNumPatrolPoints;

	Tools_SecondaryEntityFile_System::PreCreateObject();
	ToolsAVP_Node_OrientedNode::CreateGuardPoint(&pxGuardPoint, s_pxAVPToolsGuardZone->GetGuid(), pxGameNode->GetNumGuardPoints());
	Tools_SecondaryEntityFile_System::PostCreateObject();
	
	Tools_Object_System::SelectObject(this);
	
	if (pxGuardPoint)
	{
		pxGuardPoint->Position = xPosition;
		pxGuardPoint->UpdatePositionInAsuraData(false);

		// Add guardpoint to game stuff
		s_pxAVPToolsGuardZone->m_pxGameNode->AddGuardPoint(pxGuardPoint->GetGuid());
	}

	return true;
}
/// End of function 'ToolsAVP_Node_GuardZone::AddGuardPoint'. ///

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