#include "MW4Headers.hpp"
#include "aiutils.hpp"

#include "NavPoint.hpp"

#include <ElementRenderer\Element.hpp>

//#############################################################################
//###############################    NavPoint    ##############################
//#############################################################################

NavPoint::ClassData*
	NavPoint::DefaultData = NULL;

ChainOf<NavPoint *>
	*NavPoint::s_RevealedNavPoints = NULL;

ChainIteratorOf<NavPoint *>
	*NavPoint::s_RevealedNavPointsIterator = NULL;

NavPoint*
	NavPoint::s_CurrentNavPoint = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NavPoint::InitializeClass()
{
	Verify(!DefaultData);


		DefaultData =
		new ClassData(
			NavPointClassID,
			"MechWarrior4::NavPoint",
			BaseClass::DefaultData,
			0, NULL,
							 (Entity::Factory)Make,
							 (Entity::CreateMessage::Factory)CreateMessage::ConstructCreateMessage,
							 ExecutionStateEngine::DefaultData,
							 (Entity::GameModel::Factory)GameModel::ConstructGameModel,
							 (Entity::GameModel::Factory)GameModel::ConstructOBBStream,
							 (Entity::GameModel::ReadAndVerifier)GameModel::ReadAndVerify,
							 (Entity::GameModel::ModelWrite)GameModel::WriteToText,
							 (Entity::GameModel::ModelSave)GameModel::SaveGameModel,
							 AnimationStateEngine::Make
		);
	

	Verify(!s_RevealedNavPoints);
	s_RevealedNavPoints = new ChainOf<NavPoint *>(NULL);
	s_RevealedNavPointsIterator = new ChainIteratorOf<NavPoint *>(s_RevealedNavPoints);

	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NavPoint::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;

	delete s_RevealedNavPointsIterator;
	s_RevealedNavPointsIterator = NULL;

	delete s_RevealedNavPoints;
	s_RevealedNavPoints = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NavPoint*
	NavPoint::Make(
		CreateMessage *message,
		ReplicatorID *base_id
	)
{
	Check_Object(message);
	NavPoint *new_entity =
		new NavPoint(DefaultData, message, base_id, NULL);
	Check_Object(new_entity);
	return new_entity;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NavPoint::NavPoint(
	ClassData *class_data,
	CreateMessage *message,
	ReplicatorID *base_id,
	ElementRenderer::Element *element
):
	MWObject(class_data, message, base_id, element)
{
	Check_Pointer(this);
	Check_Object(message);

	visualRepresentation = DestroyedState;
	m_RadarID = -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NavPoint::~NavPoint()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	NavPoint::GetExecutionSlot()
{
	Check_Object(this);
	return NavPointExecutionSlot;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NavPoint::Reveal()
{
	Check_Object(this);

	if(!IsVisible())
	{
		SetVisibleFlag();
		AddToNavList();
		ElementRenderer::Element *element = GetElement();
		element->SetNeverCullMode();
		SyncMatrices(true);
		element->SetAlwaysCullMode();
	}
}

void NavPoint::AddToNavList()
{
	if(s_RevealedNavPoints->IsEmpty())
	{
		s_RevealedNavPoints->Add(this);
		s_RevealedNavPointsIterator->First();
	}
	else
	{
		s_RevealedNavPoints->Add(this);
	}
}

void NavPoint::RemoveFromNavList()
{
	if (s_RevealedNavPointsIterator->GetCurrent() == this)
	{
		s_RevealedNavPointsIterator->First();
	}
	if (s_CurrentNavPoint == this)
	{
		s_CurrentNavPoint = NULL;
	}
	s_RevealedNavPoints->Remove(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NavPoint*
	NavPoint::GetNextNavPoint()
{
	if(s_RevealedNavPoints->IsEmpty())
		s_CurrentNavPoint = NULL;
	else
	{
		if(s_CurrentNavPoint)
		{
			s_RevealedNavPointsIterator->Next();
			if(!s_RevealedNavPointsIterator->GetCurrent())
				s_RevealedNavPointsIterator->First();
		}

		s_CurrentNavPoint = s_RevealedNavPointsIterator->GetCurrent();
	}

	return s_CurrentNavPoint;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NavPoint*
	NavPoint::GetPreviousNavPoint()
{
	if(s_RevealedNavPoints->IsEmpty())
		s_CurrentNavPoint = NULL;
	else
	{
		if(s_CurrentNavPoint)
		{
			s_RevealedNavPointsIterator->Previous();
			if(!s_RevealedNavPointsIterator->GetCurrent())
				s_RevealedNavPointsIterator->Last();
		}

		s_CurrentNavPoint = s_RevealedNavPointsIterator->GetCurrent();
	}

	return s_CurrentNavPoint;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	NavPoint::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	
void
	NavPoint::SaveInstanceText(Page *instance_page)
{
	Check_Object(this);
	Check_Object(instance_page);

	MWObject::SaveInstanceText(instance_page);
	

}
