#pragma once

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

namespace MechWarrior4
{
	class Subsystem;
	
	void MW4DamageSecurityCheckStart();
	void MW4DamageSecurityCheckStop();

	//##########################################################################
	//###########################   MWInternalDamageObject    ##################
	//##########################################################################

	typedef InternalDamageObject__ClassData		MWInternalDamageObject__ClassData;
	typedef InternalDamageObject__Message		MWInternalDamageObject__Message;





	class MWInternalDamageObject:
		public Adept::InternalDamageObject
	{
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Inheritance Support
	//
	public:
		typedef MWInternalDamageObject__ClassData			ClassData;
		typedef MWInternalDamageObject__Message				Message;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction, Destruction, Testing
	//
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		static void
			ConstructMWInternalDamageObjectStream(
				Stuff::MemoryStream *stream,
				Stuff::Page *page
			);

		virtual void
			Save(MemoryStream *stream);

		MWInternalDamageObject(
			ClassData *class_data,
			Stuff::MemoryStream *stream
		);

		~MWInternalDamageObject();

		void
      		TestInstance() const;
	
		void*
			operator new(size_t);
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Class Data support
	//
	public:
		static ClassData 
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation support
	//
	public:

		enum{
			MissileSlotType = 0,
			ProjectileSlotType,
			BeamSlotType,
			OmniSlotType
		};

		static const char*
			SlotTypeAsciiToText(int slot_type);
		static int
			SlotTypeTextToAscii(const char *slot_type_string);

		virtual int
			VerifySubsystem(Subsystem *subsystem);
		int
			DoesHaveAvailableSlots(int slot_type, int slots_needed, bool check_omni = true, bool subtract_slot = true);
		void
			FreeAvailableSlots(int slot_type, int num);
		int
			RollCriticalHit();
		void
			InflictCriticalHit();
		void
			KillAllContainedSubsystems();
		Scalar
			TakeDamage(Stuff::Scalar damage_taken, Adept::Entity__TakeDamageMessage *message);
		int
			AddSubsystem(Subsystem *subsystem);
		Subsystem
			*GetSubsystem(int type);

		Stuff::ChainOf<Subsystem *> 
			subsystemChain;

// MSL 5.02 headshot
		Stuff::ChainOf<Subsystem *>
			destroyedSubsystemChain;

		int
			GetMissileSlotsAvailable()
				{Check_Object(this); return m_missileSlotsAvailable;}
		int
			GetProjectileSlotsAvailable()
				{Check_Object(this); return m_projectileSlotsAvailable;}
		int
			GetBeamSlotsAvailable()
				{Check_Object(this); return m_beamSlotsAvailable;}
		int
			GetOmniSlotsAvailable()
				{Check_Object(this); return m_omniSlotsAvailable;}

		void
			_InflictCriticalHit();
		Scalar
			_TakeDamage(Stuff::Scalar damage_taken, Adept::Entity__TakeDamageMessage *message);
		void
			_KillAllContainedSubsystems();

	protected:
		int
			m_missileSlotsAvailable,
			m_projectileSlotsAvailable,
			m_beamSlotsAvailable,
			m_omniSlotsAvailable,
			m_maxMissileSlots,
			m_maxProjectileSlots,
			m_maxBeamSlots,
			m_maxOmniSlots;
	};
}