#include "MW4Headers.hpp"
#include "Adept\AdeptHeaders.hpp"

#include "mw4.hpp"
#include "moverai.hpp"
#include "Adept\Interface.hpp"
#include "Adept\Application.hpp"
#include "Adept\player.hpp"
#include "torso.hpp"

#include "aimovedata.hpp"

using namespace MechWarrior4;
using namespace MW4AI;
#pragma warning (push)
#include <algorithm>
#pragma warning (pop)

CPatrolData::CPatrolData (MW4AI::CRailGraph *graph,MoverAI *owner) : CMoveData (graph,owner)
{
	m_PatrolType = PATROL_UNDEF;
	m_List.clear ();
	m_RequestList.clear ();
	m_CurRequest = -1;
	m_NodeListDirty = false;
	m_PathID = -1;
	m_StartPoint = 0;
	m_MoveType = MOVE_PATROL;
	m_Waiting = false;
}

CPatrolData::~CPatrolData (void)
{
	int i,size;

	size = m_RequestList.size ();
	for (i=0;i<size;i++)
	{
		if (m_RequestList[i])
		{
			g_PathManager->RemoveRequest (m_RequestList[i]);
			delete m_RequestList[i];
			m_RequestList[i] = NULL;
		}
	}
}
void CPatrolData::Save (MemoryStream *stream)
{
	stlport::vector<Stuff::Point3D>::iterator iter1;
	stlport::vector<MW4AI::CPathRequest *>::iterator iter2;

	*stream << m_NodeListDirty;
	*stream << m_PathID;
	*stream << m_StartPoint;
	*stream << m_CurRequest;
	*stream << m_List.size ();
	for (iter1 = m_List.begin ();iter1 != m_List.end ();iter1++)
	{
		*stream << *iter1;
	}

	*stream << m_RequestList.size ();
	for (iter2 = m_RequestList.begin ();iter2 != m_RequestList.end ();iter2)
	{
		Verify (*iter2);
		(*iter2)->Save (stream);
	}

	CMoveData::Save (stream);
}

void CPatrolData::Load (MemoryStream *stream)
{
	AutoHeap local_heap (g_MoverAIHeap);

	int i,size;

	*stream >> m_NodeListDirty;
	*stream >> m_PathID;
	*stream >> m_StartPoint;
	*stream >> m_CurRequest;
	*stream >> size;
	for (i=0;i<size;i++)
	{
		Point3D temp;
		*stream >> temp;
		m_List.push_back (temp);
	}
	*stream >> size;
	for (i=0;i<size;i++)
	{
		CPathRequest *temp;
		temp = new CPathRequest (g_MissionGraph);
		temp->Load (stream);
		m_RequestList.push_back (temp);
	}

	CMoveData::Load (stream);
}

void CPatrolData::InsertPoint (const Stuff::Point3D& loc)
{
	Point3D temp;

	AutoHeap local_heap (g_MoverAIHeap);
	temp = loc;
	ConvertPointToGrid (temp);
	inherited::InsertPoint (temp);
	if (m_List.size ())
		if (temp == m_List[m_List.size ()-1])
			return;
	m_List.push_back (temp);
	m_NodeListDirty = true;
}
void CPatrolData::InsertObject (Entity *who)
{
	inherited::InsertObject (who);
}

void CPatrolData::StartExecuting (MoverAI *ai,Stuff::Time till)
{
	CPathRequest *req;
	CRailPath *path;

	inherited::StartExecuting (ai,till);

	m_CurRequest = m_StartPoint-1;
	req = Request (-1);
	if (!req->Done ())
	{
		Executing (false);
		return;
	}
	path = req->NodePath ();
	ai->NewPath (req->DetachNodePath ());
}

void CPatrolData::Execute (MoverAI *ai,Stuff::Time till)
{
	if (!m_Waiting)
		return;

	CPathRequest *req;
	CRailPath *path;

	req = Request (CurRequest ());
	Verify (req);
	path = req->NodePath ();
	Verify (path);
	if (!req->Done ())
	{
		m_Waiting = true;
		return;
//			path->CalcPath (req->UsageAllowed ());
	}
	else
		path->Reverify (req->UsageAllowed ());

	ai->NewPath (req->DetachNodePath ());
	m_Waiting = false;
}

void CPatrolData::PathDone (MoverAI *ai,Stuff::Time till,bool failed)
{
	CPathRequest *req;
	CRailPath *path;

	inherited::PathDone (ai,till,failed);

	if (failed)
		return;

	Verify (ai->m_Vehicle);

	Stuff::Point3D temploc;
	const Vehicle__GameModel *model=NULL;
	if (ai->m_Vehicle)
		model = static_cast<const Vehicle__GameModel *> (ai->m_Vehicle->GetGameModel ()) ;
	if (ai->m_Vehicle)
		temploc = (Stuff::Point3D) ai->m_Vehicle->GetLocalToWorld ();

	CurRequest (CurRequest ()+1);
	if (CurRequest () < RequestSize ())
	{
		req = Request (CurRequest ());
		Verify (req);
		path = req->NodePath ();
		Verify (path);
		if (!req->Done ())
		{
			m_Waiting = true;
			return;
//			path->CalcPath (req->UsageAllowed ());
		}
		else
			path->Reverify (req->UsageAllowed ());

		ai->NewPath (req->DetachNodePath ());
	}
	else
	{
		switch (m_PatrolType)
		{
			case PATROL_SINGLE:
				Done (true);
				ai->SetMoveHead (Point3D (-1,-1,-1),0);
				break;
			case PATROL_LOOP:
				Executing (false);
				m_StartPoint = 0;
				CreateRequests (temploc,MW4AI::ConvertTypetoUsage (model->moveTypeFlag));
				StartExecuting (ai,till);
				break;
			case PATROL_SEESAW:
				Executing (false);
				m_StartPoint = 0;
				ReversePatrolList ();
				CreateRequests (temploc,MW4AI::ConvertTypetoUsage (model->moveTypeFlag));
				StartExecuting (ai,till);
				break;
		}
//				Done (true);
	}
}

void CPatrolData::CreatePlaneRequests (const Stuff::Point3D& start)
{
	m_RequestList.clear ();
	inherited::CreatePlaneRequests (start);
}

void CPatrolData::CreateRequests (const Stuff::Point3D& start,int usageflags)
{
	Point3D loc,third,fred;
	AutoHeap local_heap (g_MoverAIHeap);

	inherited::CreateRequests (start,usageflags);

	int i,size;
	size = m_RequestList.size ();
	for (i=0;i<size;i++)
	{
		if (m_RequestList[i])
		{
			g_PathManager->RemoveRequest (m_RequestList[i]);
			delete m_RequestList[i];
			m_RequestList[i] = NULL;
		}
	}

	m_RequestList.clear ();
	m_PathRequest = g_PathManager->AddRequest (gos_GetElapsedTime (),m_Graph,start,m_List[m_StartPoint],usageflags,m_AI,m_AI->AllowTenMeter ());

	size = m_List.size ();
	for (i=0;i<size-1;i++)
	{

		CPathRequest *req;

		req = g_PathManager->AddRequest (gos_GetElapsedTime ()+(1.0*i) ,m_Graph,m_List[i],m_List[i+1],usageflags,m_AI,m_AI->AllowTenMeter ());
		Check_Pointer (req);
		m_RequestList.push_back (req);
	}
}
bool CPatrolData::operator== (const CPatrolData& p1)
{
	if (!inherited::operator== ((inherited)p1))
		return false;
	if (m_PathID != p1.m_PathID)
		return false;
	return true;
}

Stuff::Point3D CPatrolData::Location (int id)
{
	Verify (id>=0);
	Verify (id<m_List.size ());
	return m_List[id];
}

int CPatrolData::LocationSize (void) const
{
	return m_List.size ();
}

void CPatrolData::ReversePatrolList (void)
{
	stlport::vector<Stuff::Point3D>::iterator first,last;

	AutoHeap local_heap (g_MoverAIHeap);
	first = m_List.begin ();
	last = m_List.end ();
	stlport::reverse (first,last);
}

void CPatrolData::SetupPath (Path *path)
{
	Check_Object (path);
	m_PathID = path->objectID;

	int size,i;
	size = path->pathPoints.size ();
	for (i=0;i<size;i++)
	{
		InsertPoint (path->pathPoints[i]);
	}
}

