#pragma once

#include "MW4.hpp"
#include "aiutils.hpp"

#include <Adept\Entity.hpp>

namespace MechWarrior4
{
	class Objective;

	const int ObjectiveTextLength = 255;

	int CountVisibleObjectives (void);
	const char* ObjectiveText (int id);

	//##########################################################################
	//##################        ObjectiveRenderer      #########################
	//##########################################################################

	class ObjectiveRenderer :	public Stuff::Plug
	{
	protected:
		Stuff::Time m_StartTime,m_HelpStartTime;
		Stuff::Time m_DelayTime,m_HelpDelayTime;
		bool m_ShowHelp;

	public:
		ObjectiveRenderer();
		~ObjectiveRenderer();
	
		void Execute();
		void Help (Objective *helpmessage,Stuff::Time delay);
		void DrawWindow(int size);
		void ResetTime (void);
		void ToggleObjective (void);

		static ObjectiveRenderer *Instance;

	};

	
	//##########################################################################
	//###############    Objective::ExecutionStateEngine     ###################
	//##########################################################################

	class Objective__ExecutionStateEngine:
		public Adept::Entity__ExecutionStateEngine
	{
	public:
		static void InitializeClass();
		static void	TerminateClass();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef Objective__ExecutionStateEngine* (*Factory)(Objective *objective , FactoryRequest *request);

		static Objective__ExecutionStateEngine*	Make(Objective *objective , FactoryRequest *request);

	protected:
		Objective__ExecutionStateEngine(ClassData *class_data,Objective *objective,FactoryRequest *request);

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State stuff
	//
	public:
		enum {
			RevealedState = Adept::Entity__ExecutionStateEngine::StateCount,
			StateCount
		};

	protected:
		static const StateEntry StateEntries[];

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

	//##########################################################################
	//##################    Objective::CreateMessage    ########################
	//##########################################################################

	class Objective__CreateMessage : public Adept::Entity__CreateMessage
	{
	public:
		int objectiveID;
		int objectiveState;
		bool primaryObjective;
		bool visibleObjective;
		int failtextID;
		int succeedtextID;
		int neutraltextID;
		int descriptiontextID;
		bool helpMessage;
		char failtext[ObjectiveTextLength];
		char succeedtext[ObjectiveTextLength];
		char neutraltext[ObjectiveTextLength];
		char descriptiontext[ObjectiveTextLength];

		Objective__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const Adept::ResourceID& instance_id,
			const Stuff::LinearMatrix4D &creation_matrix,
			Stuff::Scalar age,
			int execution_state,
			int name_id,
			int entity_alignment,
			int objective_id,
			bool primary,
			bool visible,
			bool help,
			int objstate,
			int failID,
			int succeedID,
			int neutralID,
			int descriptionID,
			const char *fail,
			const char *succeed,
			const char *neutral,
			const char *description
		):
			Adept::Entity__CreateMessage(
				length,
				priority,
				message_flags,
				class_id,
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment
			)
				{
					objectiveID = objective_id;
					objectiveState = objstate;
					primaryObjective = primary;
					visibleObjective = visible;
					failtextID = failID;
					succeedtextID = succeedID;
					neutraltextID = neutralID;
					descriptiontextID = descriptionID;
					helpMessage = help;
					
					Check_Pointer(fail);
					Str_Copy(failtext, fail, sizeof(failtext));
					
					Check_Pointer(succeed);
					Str_Copy(succeedtext, succeed, sizeof(succeedtext));
					
					Check_Pointer(neutral);
					Str_Copy(neutraltext, neutral, sizeof(neutraltext));

					Check_Pointer(description);
					Str_Copy(descriptiontext, description, sizeof(descriptiontext));
				}

		static void ConstructCreateMessage(Script *script);
	};
	
	//##########################################################################
	//###########################   Objective    ###############################
	//##########################################################################

	typedef Adept::Entity__ClassData						Objective__ClassData;
	typedef Adept::Entity__Message							Objective__Message;
	typedef Adept::Entity__GameModel						Objective__GameModel;
	
	class Objective:
		public Adept::Entity
	{
	public:
		static void InitializeClass();
		static void TerminateClass();

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef Objective__ClassData						ClassData;
		typedef Objective__GameModel						GameModel;
		typedef Objective__Message							Message;
		typedef Objective__ExecutionStateEngine				ExecutionStateEngine;
		typedef Objective__CreateMessage					CreateMessage;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:

		enum
		{
			Objective_Failed,						// player has failed this objective
			Objective_Succeeded,				// player has succeeded this objetive
			Objective_Neutral					// player is currently working on it
		};

		bool m_VisibleObjective;			// true for visible
		bool m_Primary;								// true for primary, false for secondary
		bool m_HelpMessage;						// true if this is a help message
		int m_ObjectiveState;					// above enum

		int m_ObjectiveID;
		char m_FailText[ObjectiveTextLength];
		char m_SucceedText[ObjectiveTextLength];
		char m_NeutralText[ObjectiveTextLength];
		char m_DescriptionText[ObjectiveTextLength];

		char m_LoadedFailText[ObjectiveTextLength];
		char m_LoadedSucceedText[ObjectiveTextLength];
		char m_LoadedNeutralText[ObjectiveTextLength];
		char m_LoadedDescriptionText[ObjectiveTextLength];

		int m_FailTextID;
		int m_SucceedTextID;
		int m_NeutralTextID;
		int m_DescriptionTextID;

//		HGOSFONT3D font;

		static Objective* Make(CreateMessage *message,Adept::ReplicatorID *base_id);
		Adept::Replicator::CreateMessage* SaveMakeMessage(Stuff::MemoryStream *stream, Adept::ResourceFile *res_file);
		void SaveInstanceText(Stuff::Page *page);
		void DisplayText(const char *text_string, int x_loc, int y_loc);
		void DrawTextWindow();
		void SetName (const char *,bool);

	protected:
		Objective(ClassData *class_data,CreateMessage *message,Adept::ReplicatorID *base_id,ElementRenderer::Element *element);
	
		~Objective();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data support
	//
	public:
		static ClassData *DefaultData;
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Support
	//
	public:
		 int
			GetTableArray()
			{Check_Object(this); return Adept::NameTable::ObjectiveArray;}
		 void DrawObjective(Stuff::Scalar x_loc, Stuff::Scalar y_loc);
		 void PreCollisionExecute(Stuff::Time till);
		 void Succeed (void);
		 void Fail (void);
		 void Reveal (void);
		 void Hide (void);
		 int Status (void);
		 bool Visible (void);
		 bool HelpMessage (void);
		 void ShowHelp (Stuff::Time time);
		 const char *CurrentText (bool ignorevisual=false);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:

		void TestInstance() const;
	};


	inline
		Objective__ExecutionStateEngine::Objective__ExecutionStateEngine(
			ClassData *class_data,
			Objective *objective,
			FactoryRequest *request
		):
		Adept::Entity__ExecutionStateEngine(class_data, objective, request)
	{
	}

}


