#pragma once

#include "MW4.hpp"
#include "Vehicle.hpp"

namespace Adept
{
	class DamageObject;
}

namespace MechWarrior4
{	
	class Mech;
	class Weapon;
	class MWInternalDamageObject;
	class MFB;

	

	//##########################################################################
	//############################    MFB    ###################################
	//##########################################################################

	//-------------------------------------------------------------------------
	// The following helper classes must always be typedef'd or overriden by an
	// inheritor
	//
	typedef Vehicle__Message				MFB__Message;
	typedef Vehicle__UpdateMessage			MFB__UpdateMessage;
	typedef Vehicle__CreateMessage			MFB__CreateMessage;
	typedef Vehicle__ClassData				MFB__ClassData;

	extern DWORD Executed_MFB_Count;

	//##########################################################################
	//###############		MFB::GameModel    ##################################
	//##########################################################################

	class MFB__GameModel:
		public Vehicle::GameModel
	{
	public:
		typedef Vehicle::GameModel BaseClass;
		
		Adept::ResourceID
			m_repairEffectResource;

		Stuff::Vector3D m_repairCenterOffset;
		Stuff::Scalar m_repairDistance;

		enum {
			RepairEffectResourceAttributeID = Vehicle__GameModel::NextAttributeID,
			RepairCenterOffsetAttributeID,
			RepairDistanceAttributeID,
			NextAttributeID
		};

		static bool
			ReadAndVerify(
				MFB__GameModel *model,
				ModelAttributeEntry *attribute_entry,
				const char *data,
				char **error,
				int error_buffer = 128
			);

		static void
			ConstructGameModel(Script *script);	
	};

	//##########################################################################
	//###############		MFB::ExecutionStateEngine    #######################
	//##########################################################################

	class MFB__ExecutionStateEngine:
		public Vehicle::ExecutionStateEngine
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Vehicle::ExecutionStateEngine BaseClass;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef MFB__ExecutionStateEngine*
			(*Factory)(
				MFB *entity,
				FactoryRequest *request
			);

		static MFB__ExecutionStateEngine*
			Make(
				MFB *mover,
				FactoryRequest *request
			);

	protected:
		MFB__ExecutionStateEngine(
			ClassData *class_data,
			MFB *mover,
			FactoryRequest *request
		);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data support
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State stuff
	//
	public:
		enum {
			RepairState = Vehicle::ExecutionStateEngine::StateCount,
			OpeningMotionState,
			StateCount
		};

	protected:
		static const StateEntry
			StateEntries[];

	public:
		int
			RequestState(
				int new_state,
				void* data = NULL
			);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
		  	TestInstance() const;
	};

	//-----------------------  End of inheritance stuff ------------------------

	class MFB:
		public Vehicle
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Vehicle BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef MFB__ClassData					ClassData;
		typedef MFB__GameModel					GameModel;
		typedef MFB__Message					Message;
		typedef MFB__ExecutionStateEngine		ExecutionStateEngine;
		typedef MFB__CreateMessage				CreateMessage;
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static MFB*
			Make(
				CreateMessage *message,
				ReplicatorID *base_id
			);

		void
			SaveInstanceText(Stuff::Page *page);

	protected:
		MFB(
			ClassData *class_data,
			CreateMessage *message,
			ReplicatorID *base_id,
			ElementRenderer::Element *element
		);
		
		void
			Respawn(Adept::Entity::CreateMessage *message);
		void
			CommonCreation(CreateMessage *message);

		void
			Reuse(
				const CreateMessage *message,
				ReplicatorID *base_id
			);

		~MFB();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data support
	//
	public:
		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Game Model Support
	//
	public:
		const GameModel*
			GetGameModel()
				{
					Check_Object(this);
					return Cast_Pointer(const GameModel*,gameModelResource.GetPointer());
				}

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution Support
	//
	public:
		MoverAI *m_CurrentMechUsing;					// for the ai to use to store which mech is about to the fieldbase
		void
			TurnOn();
		void
			PreCollisionExecute(Stuff::Time till);
		void
			PostCollisionExecute(Stuff::Time till);
		bool
			CollisionHandler(
				Stuff::LinearMatrix4D *new_position,
				Stuff::DynamicArrayOf<CollisionData> *collisions
			);
		void
			RepairTargetMech(Stuff::Scalar time_slice);
		void
			StartNewMech(Mech *new_mech);
		void
			ShutMFBDown();
		void
			CreateRepairEffect();
		void
			ReactToDestruction(int damage_mode, int damage_type);

		enum{
			FixingGimpState = 0,
			ReloadingAmmoState,
			ReloadingCoolantState,
			FixingInternalState,
			FixingArmorState
		};
		
		typedef ChainIteratorOf<Weapon *>
			WeaponIteratorType;
		typedef SortedChainIteratorOf<MWInternalDamageObject *, int>
			InternalIteratorType;
		typedef SortedChainIteratorOf<Adept::DamageObject *, int>
			ArmorIteratorType;

		bool IsWithin(Entity *target,Vector3D offset,Scalar distance,bool ignorey = false);
		static MFB *IsWithinMFB(Mech *mech);

		static Stuff::ChainOf<MFB*>
			*s_MFBs;

	protected:
		//Scalar m_RepairDistance;
		Stuff::SlotOf<Mech *>
			m_repairingMech;
		Stuff::SlotOf<Effect *>
			m_repairEffect;
		int
			m_currentState;
		Stuff::Time
			m_nextRepairTime;

		WeaponIteratorType
			*m_weaponIterator;
		InternalIteratorType
			*m_internalIterator;
		ArmorIteratorType
			*m_armorIterator;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
      		TestInstance() const;
	};

	inline
		MFB__ExecutionStateEngine::MFB__ExecutionStateEngine(
			ClassData *class_data,
			MFB *mover,
			FactoryRequest *request
		):
			BaseClass(class_data, mover, request)
	{
	}

}
