#pragma once

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

namespace Adept
{
	class Site;
}

namespace MechWarrior4
{
	class VehicleInterface;
	class MWMover;

	//##########################################################################
	//##################    BeamEntity::CreateMessage    #######################
	//##########################################################################

	class BeamEntity__CreateMessage:
		public Adept::Entity__CreateMessage
	{
	public:
		typedef Adept::Entity__CreateMessage BaseClass;

		Adept::ReplicatorID
			inflictingEntityID;
		char
			siteName[128];
		Stuff::Point3D
			targetPoint;
		Adept::ReplicatorID
			targetID;
		Stuff::Normal3D
			targetNormal;
		Stuff::Scalar
			damageAmount;
		BYTE
			targetMaterial;
		Stuff::Scalar
			heatAmount;
		Stuff::Scalar 
			maxDistance;
// MSL 5.03 Min Distance
//		Stuff::Scalar
//			minDistance;

		int 
			itemID;

		BeamEntity__CreateMessage(
			size_t length,
			int priority,
			int message_flags,
			Stuff::RegisteredClass::ClassID class_id,
			int replicator_flags,
			const ResourceID& instance_id,
			const Stuff::LinearMatrix4D &creation_matrix,
			Stuff::Scalar age,
			int execution_state,
			int name_id,
			int entity_alignment,
			Adept::ReplicatorID inflicting_entity,
			const char *site_name,
			Stuff::Point3D target_point,
			Adept::ReplicatorID target_id,
			Stuff::Normal3D target_normal,
			Stuff::Scalar damage_amount,
			Stuff::Scalar heat_amount,
			BYTE target_material,
			Stuff::Scalar max_distance,
// MSL 5.03 Min Distance
//			Stuff::Scalar min_distance,
			int itemID
		):
			Adept::Entity__CreateMessage(
				length, 
				priority, 
				message_flags, 
				class_id, 
				replicator_flags,
				instance_id,
				creation_matrix,
				age,
				execution_state,
				name_id,
				entity_alignment
			),
				inflictingEntityID(inflicting_entity),
				targetPoint(target_point),
				targetID(target_id),
				targetNormal(target_normal),
				damageAmount(damage_amount),
				targetMaterial(target_material),
				heatAmount(heat_amount),
				maxDistance(max_distance),
// MSL 5.03 Min Distance
//				minDistance(min_distance),
				itemID(itemID)
				{
					Check_Pointer(site_name);
					Str_Copy(siteName, site_name, 128);
				}
	};

	//##########################################################################
	//###########################   BeamEntity::GameModel    ###################
	//##########################################################################

	class BeamEntity__GameModel:
		public Adept::Entity__GameModel
	{
	public:
		typedef Adept::Entity__GameModel BaseClass;
		
		Adept::ResourceID
			hitEffectMaterialTable;
		Adept::ResourceID
			hitEffectResourceID;
		Adept::ResourceID
			damageDecalResourceID;

		enum {
			HitEffectResourceAttributeID = Entity__GameModel::NextAttributeID,
			DamageDecalResourceAttributeID,
			NextAttributeID
		};

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

		static void
			ConstructGameModel(Script *script);
	};

	//##########################################################################
	//###########################   BeamEntity    ##############################
	//##########################################################################

	typedef Adept::Entity__ClassData						BeamEntity__ClassData;
	typedef Adept::Entity__Message							BeamEntity__Message;
	typedef Adept::Entity__ExecutionStateEngine				BeamEntity__ExecutionStateEngine;
	
	extern DWORD Executed_Beam_Count;

	class BeamEntity:
		public Adept::Entity
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef Adept::Entity BaseClass;

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef BeamEntity__ClassData							ClassData;
		typedef BeamEntity__GameModel							GameModel;
		typedef BeamEntity__Message								Message;
		typedef BeamEntity__ExecutionStateEngine				ExecutionStateEngine;
		typedef BeamEntity__CreateMessage						CreateMessage;


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		static BeamEntity* 
			Make(
				CreateMessage *message,
				ReplicatorID *base_id
			);

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

		~BeamEntity();

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Flag and attribute Support
	//
	public:
		enum 
		{
			DefaultFlags = HermitMode
		};

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Execution Support
	//
	public:
		void
			PostCollisionExecute(Stuff::Time till);
		Adept::ReplicatorID
			MoveBeam();
		void
			PlayWaterEffectIfNecessary(Line3D target_Line);
		void
			CreateHitEffect();
		virtual void
			InflictDamage(Adept::ReplicatorID damaged_entity = ReplicatorID::Null);
		void
			PlaceDamageDecal();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	public:
		enum {
			BeamDistanceAttributeID = Adept::Entity::NextAttributeID,
			TargetPointAttributeID,
			BeamHitSFXAttributeID,
			BeamStatusAttributeID, 
			NextAttributeID
		};

	public:
		//
		// Attributes
		//
		int
			beamHitSFX;
		bool
			beamStatus;

		Stuff::Scalar
			beamDistanceAttribute;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data support
	//
	public:
		static ClassData
			*DefaultData;
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Support
	//
	public:
		SlotOf<Adept::Site*>
			siteEntity;
		Stuff::Point3D
			targetPoint;
		Stuff::Point3D
			targetOffset;
		SlotOf<Adept::Entity*>
			targetEntity;
		Stuff::Normal3D
			targetNormal;
		Stuff::Scalar
			damageAmount;
		Stuff::Scalar
			heatAmount;
		Adept::ReplicatorID
			inflictingEntityID;
		MWObject 
			*inflictingVehicle;
		BYTE
			targetMaterial;
		Stuff::Scalar
			maxDistance;
// MSL 5.03 Min Distance
//		Stuff::Scalar
//			minDistance;
		int
			itemID;
		bool
			rayCastDone;

// MSL 5.06 Armor Mode
		int
			m_ArmorMode;

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


