//===========================================================================//
// File:	aiMoveData.hpp																	     //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
//	07/13/99  AHF	Created File                  //
//---------------------------------------------------------------------------//
// Copyright (C) 1999, Microsoft										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "ai.hpp"
#include "aiutils.hpp"
#include "rail_move.hpp"
#include "vehicle.hpp"
#include "path.hpp"
#pragma warning (push)
#include <vector>
#pragma warning (pop)


namespace MechWarrior4
{

	enum Patrol_Type
	{
		PATROL_UNDEF,
		PATROL_SINGLE,
		PATROL_LOOP,
		PATROL_SEESAW
	};

	enum Move_Type
	{
		MOVE_UNDEF,
		MOVE_LOOKOUT,
		MOVE_PATROL,
		MOVE_RIGIDPATROL,
		MOVE_FLEE,
		MOVE_FOLLOW,
		MOVE_SIT,
		MOVE_LOCPOINT,
		MOVE_OBJECT,
		MOVE_SEMIPATROL
	};

	const Stuff::Time FollowCalcDelta = 5.0f;

#ifdef _ARMOR
	class CMoveData : public Signature
#else
	class CMoveData
#endif
	{
	private:
		CMoveData (void);
	protected:

		MoverAI *m_AI;
		Move_Type m_MoveType;
		Stuff::Scalar m_Speed;
		MW4AI::CRailGraph *m_Graph;
		MW4AI::CPathRequest *m_PathRequest;			// is the first one for a patrol
		bool m_DidCommand;
		bool m_Executing;
		bool m_Done;
		bool m_ClearEnd;
		int m_Usage;


	public:
		CMoveData (MW4AI::CRailGraph *graph,MoverAI *owner);

		virtual ~CMoveData (void);

		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);

		Move_Type MoveType (void) const
		{	return m_MoveType;}

		virtual void InsertPoint (const Stuff::Point3D& loc);
		virtual void InsertObject (Entity *who);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void Execute (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual void CreatePlaneRequests (const Stuff::Point3D& start);

		virtual bool operator== (const CMoveData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;

		MW4AI::CRailGraph *Graph (void)
		{ return m_Graph; }

		void Speed (Stuff::Scalar speed)
		{ m_Speed = speed; }
		virtual Stuff::Scalar Speed (void) const;

		bool ClearEnd (void) const
		{ return m_ClearEnd; }
		void ClearEnd (bool p1)
		{ m_ClearEnd = p1; }

		bool Executing (void) const
		{ return m_Executing; }
		void Executing (bool execute)
		{ m_Executing = execute; }

		bool Done (void) const
		{ return m_Done; }
		virtual void Done (bool done)
		{ m_Done = done; }

		bool DidCommand (void) const
		{ return m_DidCommand; }
		void DidCommand (bool value)
		{ m_DidCommand = value; }

		MW4AI::CPathRequest *Request (void)
		{ return m_PathRequest; }


		void TestInstance() const
		{ }

	};

	class CPatrolData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Patrol_Type m_PatrolType;
		bool m_NodeListDirty;
		ObjectID m_PathID;
		int m_StartPoint;
		bool m_Waiting;
		stlport::vector<Stuff::Point3D> m_List;
		stlport::vector<MW4AI::CPathRequest *> m_RequestList;
		int m_CurRequest;						// which request we are currently executing

	public:
		CPatrolData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CPatrolData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);

		virtual void InsertPoint (const Stuff::Point3D& loc);
		virtual void InsertObject (Entity *who);

		virtual void Execute (MoverAI *ai,Stuff::Time till);
		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual void CreatePlaneRequests (const Stuff::Point3D& start);
		virtual bool operator== (const CPatrolData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;

		MW4AI::CPathRequest *Request (int id)
		{
			Verify (id>=-1);
			if (id == -1)
				return m_PathRequest;
			Verify (id <m_RequestList.size ());
			return m_RequestList[id];
		}
		int RequestSize (void) const
		{	return m_RequestList.size (); }

		// new commands
		void SetupPath (Path *path);
		void StartPathAt (int index)
		{ m_StartPoint = index; }

		void PathID (int newid)
		{ m_PathID = newid; }
		int PathID (void) const
		{ return m_PathID; }

		int CurRequest (void) const
		{ return m_CurRequest; }
		void CurRequest (int value)
		{ m_CurRequest = value; }

		void PatrolType (Patrol_Type type)
		{ m_PatrolType = type; }
		Patrol_Type PatrolType (void) const
		{ return m_PatrolType; }

		void ReversePatrolList (void);

		bool Dirty (void)
		{ return m_NodeListDirty; }
	};

	class CRigidPatrolData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Patrol_Type m_PatrolType;
		bool m_NodeListDirty;
		ObjectID m_PathID;
		int m_StartPoint;
		stlport::vector<Stuff::Point3D> m_List;
		int m_InMove;						// which request we are currently executing
		int m_InMoveDir;

	public:
		CRigidPatrolData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CRigidPatrolData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		virtual void InsertPoint (const Stuff::Point3D& loc);
		virtual void InsertObject (Entity *who);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void Execute (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual void CreatePlaneRequests (const Stuff::Point3D& start);
		virtual bool operator== (const CRigidPatrolData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;

		// new commands
		void SetupPath (Path *path);
		void StartPathAt (int index)
		{ m_StartPoint = index; }

		void PathID (int newid)
		{ m_PathID = newid; }
		int PathID (void) const
		{ return m_PathID; }

		void PatrolType (Patrol_Type type)
		{ m_PatrolType = type; }
		Patrol_Type PatrolType (void) const
		{ return m_PatrolType; }

		void ReversePatrolList (void);

		bool Dirty (void)
		{ return m_NodeListDirty; }
	};

	class CFollowData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Entity        *m_WhoFollow;
		Stuff::Scalar m_OffsetX,m_OffsetZ;
		mutable Stuff::Time   m_LastCalcTime;
		Stuff::Point3D m_LastEndPoint;
		Stuff::Scalar m_MaxSpeed;

		void UpdateFollow (MoverAI *ai,Stuff::Time till);
		Stuff::Point3D FollowPoint (bool& modified) const;

	public:
		CFollowData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CFollowData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		virtual void InsertObject (Entity *who);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void Execute (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual bool operator== (const CFollowData& p1);
		virtual Stuff::Scalar Speed (void) const;
	
		virtual void Done (bool done)
		{		}

		// new commands
		Entity *Follow (void)
		{ return m_WhoFollow; }

		Stuff::Scalar FollowXOffset (void) const
		{ return m_OffsetX; }
		Stuff::Scalar FollowZOffset (void) const
		{ return m_OffsetZ; }
		Stuff::Scalar MaxSpeed (void) const
		{ return m_MaxSpeed; }

		void FollowXOffset (Stuff::Scalar p1)
		{ m_OffsetX = p1; }
		void FollowZOffset (Stuff::Scalar p1)
		{ m_OffsetZ = p1; }
		void MaxSpeed (Stuff::Scalar p1)
		{ m_MaxSpeed = p1; }
		virtual Stuff::Point3D Location (int id)
		{	bool fred; return FollowPoint (fred); }
		virtual int LocationSize (void) const
		{ return 1; }

		Stuff::Time LastCalcTime (void) const
		{ return m_LastCalcTime; }
	};

	class CLookoutData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		bool m_LookDir;
		float m_LastLookSpeed;
		bool m_Slowing;

	public:
		CLookoutData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CLookoutData (void) {}
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void Execute (MoverAI *ai,Stuff::Time till);
	};

	class CFleeData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Entity *m_From;
		Stuff::Point3D m_FleeLoc;
	public:
		CFleeData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CFleeData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		virtual void InsertObject (Entity *who);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual void CreatePlaneRequests (const Stuff::Point3D& start);
		virtual bool operator== (const CFleeData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;

		// new commands
		Entity *FleeFrom (void)
		{ return m_From; }

		int FleeDistance (Entity *src);
	};

	class CSitData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

	public:
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		CSitData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CSitData (void);
	};

	class CMoveLocPointData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Stuff::Point3D m_Location;
	public:
		CMoveLocPointData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CMoveLocPointData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		virtual void InsertPoint (const Stuff::Point3D& loc);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual bool operator== (const CMoveLocPointData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;

		// new commands
		Stuff::Point3D LocPoint (void) const
		{ return m_Location; }
		void LocPoint (Stuff::Point3D p1)
		{ m_Location = p1; }
	};

	class CMoveObjectData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Entity *m_TargetObject;
	public:
		CMoveObjectData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CMoveObjectData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);
		virtual void InsertObject (Entity *who);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual bool operator== (const CMoveObjectData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;

		// new commands
		Entity *TargetObject (void)
		{ return m_TargetObject; }
	};

	class CSemiPatrolData : public CMoveData
	{
	private:
		typedef CMoveData inherited;

		Patrol_Type m_PatrolType;
		bool m_NodeListDirty;
		ObjectID m_PathID;
		int m_StartPoint;
		bool m_PathWorking;
		stlport::vector<Stuff::Point3D> m_List;
		int m_CurRequest;						// which request we are currently executing

	public:
		CSemiPatrolData (MW4AI::CRailGraph *graph,MoverAI *owner);
		~CSemiPatrolData (void);
		
		virtual void Save (MemoryStream *stream);
		virtual void Load (MemoryStream *stream);

		virtual void InsertPoint (const Stuff::Point3D& loc);
		virtual void InsertObject (Entity *who);

		virtual void StartExecuting (MoverAI *ai,Stuff::Time till);
		virtual void PathDone (MoverAI *ai,Stuff::Time till,bool failed);
		virtual void Execute (MoverAI *ai,Stuff::Time till);

		MW4AI::CPathRequest *NeedPathRequest (const Point3D& loc,int usageflags);

		void UpdatePathRequest (const Point3D& loc,MW4AI::CPathRequest *req);

		virtual void CreateRequests (const Stuff::Point3D& start,int usageflags);
		virtual void CreatePlaneRequests (const Stuff::Point3D& start);
		virtual bool operator== (const CSemiPatrolData& p1);
		virtual Stuff::Point3D Location (int id);
		virtual int LocationSize (void) const;
		int RequestSize (void) const
		{	return LocationSize ();}

		// new commands
		void SetupPath (Path *path);
		void StartPathAt (int index)
		{ m_StartPoint = index; }

		void PathID (int newid)
		{ m_PathID = newid; }
		int PathID (void) const
		{ return m_PathID; }

		int CurRequest (void) const
		{ return m_CurRequest; }
		void CurRequest (int value)
		{ m_CurRequest = value; }

		void PatrolType (Patrol_Type type)
		{ m_PatrolType = type; }
		Patrol_Type PatrolType (void) const
		{ return m_PatrolType; }

		void ReversePatrolList (void);

		bool Dirty (void)
		{ return m_NodeListDirty; }
	};

}

