//===========================================================================//
// File:	Subsystem.hpp													
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 09/09/98  JSE  Inital base class based off of Shadowrun/Adept       
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "MW4.hpp"
#include <Adept\Entity.hpp>

namespace MechWarrior4
{
	class MWObject;
	class Vehicle;
	class HeatManager;
	class Subsystem;
	class Subsystem__GameModel;
	class Subsystem__ClassData;


	//##########################################################################
	//###############    Subsystem::ExecutionStateEngine     ###################
	//##########################################################################

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

		typedef Adept::Entity__ExecutionStateEngine BaseClass;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef Subsystem__ExecutionStateEngine*
			(*Factory)(
				Subsystem *subsystem,
				FactoryRequest *request
			);

		static Subsystem__ExecutionStateEngine*
			Make(
				Subsystem *subsystem,
				FactoryRequest *request
			);

	protected:
		Subsystem__ExecutionStateEngine(
			ClassData *class_data,
			Subsystem *subsystem,
			FactoryRequest *request
		);

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

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

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

	protected:
		static const StateEntry
			StateEntries[];

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

	//##########################################################################
	//###########################   Subsystem::GameModel    ####################
	//##########################################################################

	class Subsystem__GameModel:
		public Adept::Entity::GameModel
	{
	public:
		typedef Adept::Entity::GameModel BaseClass;

		Stuff::Scalar
			tonage;
		int
			battleValue;
		int
			totalSlotsTaken;
		int
			slotType;
		int
			itemID;
		
		enum {
			TotalSlotsTakenAttributeID = Entity__GameModel::NextAttributeID,
			TonageAttributeID,
			BattleValueAttributeID,
			ItemIDAttributeID,
			NextAttributeID
		};

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

		static void
			ConstructGameModel(Script *script);
	};

	//##########################################################################
	//##################    Subsystem::CreateMessage    ########################
	//##########################################################################

	class Subsystem__CreateMessage:
		public Adept::Entity__CreateMessage
	{
	public:
		typedef Adept::Entity__CreateMessage BaseClass;
	
		int
			subsystemIndex;
		BYTE
			locationID;
		int
			criticalHitsTaken;

		Subsystem__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 subsystem_index,
			BYTE location_id,
			int critical_hits
		):
			Adept::Entity__CreateMessage(
				length, 
				priority, 
				message_flags, 
				class_id, 
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment
			),
			subsystemIndex(subsystem_index),
			locationID(location_id),
			criticalHitsTaken(critical_hits)
				{}

		static void
			ConstructCreateMessage(Script *script);
	};

	//##########################################################################
	//###########################   Subsystem    ###############################
	//##########################################################################

	typedef Adept::Entity__Message						Subsystem__Message;
	
	class Subsystem:
		public Adept::Entity
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Adept::Entity BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef Subsystem__ClassData							ClassData;
		typedef Subsystem__GameModel							GameModel;
		typedef Subsystem__Message								Message;
		typedef Subsystem__ExecutionStateEngine					ExecutionStateEngine;
		typedef Subsystem__CreateMessage						CreateMessage;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static Subsystem* 
			Make(
				CreateMessage *message,
				Adept::ReplicatorID *base_id
			);
		
		Adept::Replicator::CreateMessage*
			SaveMakeMessage(MemoryStream *stream, Adept::ResourceFile *res_file);

		virtual void
			SaveInstanceText(Stuff::Page *page);
		void
			Respawn(Adept::Entity::CreateMessage *message);
		MWObject* 
			GetParentVehicle();
		Vehicle*
			GetParentAsVehicle();

		void
			BecomeInteresting(bool render_me);

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

		~Subsystem();

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Stream Creation Support
	//
	public:
		typedef void
			(*StreamCreate)(
				Adept::ResourceID data_list,
				Stuff::MemoryStream *stream
			);

		static void
			CreateStream(
				Adept::ResourceID data_list,
				Stuff::MemoryStream *stream
			);

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

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

		//Must call the inherited virtual function!!!!
		virtual bool 
			ConnectSubsystem();
		virtual bool
			DisconnectSubsystem();

		virtual void
			ConnectHeatManager(HeatManager *heat_manager)
				{}
		
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Simulation Support
		//
		int critHitsTaken;    //0 to totalCrits
		
		int subsystemIndex;

		BYTE	  
			internalLocation;
		int
			containedInSlotType;

		virtual bool
			TakeCriticalHit();
		virtual void
			DestroySubsystem();

		Vehicle
			*parentAsVehicle;

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

	inline
		Subsystem__ExecutionStateEngine::Subsystem__ExecutionStateEngine(
			ClassData *class_data,
			Subsystem *subsystem,
			FactoryRequest *request
		):
		Adept::Entity__ExecutionStateEngine(class_data, subsystem, request)
	{
	}
}


