#pragma once

#include "MW4.hpp"
#include "ProjectileWeapon.hpp"

namespace MechWarrior4
{

	class RTXWeaponSub; 


	typedef ProjectileWeapon__CreateMessage				RTXWeaponSub__CreateMessage;
	// typedef ProjectileWeapon__ExecutionStateEngine		RTXWeaponSub__ExecutionStateEngine;
	typedef ProjectileWeapon__Message					RTXWeaponSub__Message;
	typedef ProjectileWeapon__ClassData					RTXWeaponSub__ClassData;

	//##########################################################################
	//###############    Projectile::ExecutionStateEngine    ###################
	//##########################################################################

	class RTXWeaponSub__ExecutionStateEngine :
		public ProjectileWeapon__ExecutionStateEngine
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

		typedef ProjectileWeapon__ExecutionStateEngine BaseClass;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:
		typedef RTXWeaponSub__ExecutionStateEngine*
			(*Factory)(
				RTXWeaponSub *weapon,
				FactoryRequest *request
			);

		static RTXWeaponSub__ExecutionStateEngine*
			Make(
				RTXWeaponSub *weapon,
				FactoryRequest *request
			);

	protected:
		RTXWeaponSub__ExecutionStateEngine(
			ClassData *class_data,
			RTXWeaponSub *weapon,
			FactoryRequest *request
		);

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

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State stuff
	//
	public:
		enum {
			JammedState = ProjectileWeapon__ExecutionStateEngine::StateCount,
			RechargingState,
			StateCount
		};

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

	protected:
		static const StateEntry
			StateEntries[];

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

		
	//##########################################################################
	//#####################   RTXWeaponSub::GameModel    #######################
	//##########################################################################

	class RTXWeaponSub__GameModel:
		public ProjectileWeapon::GameModel
	{
	public:
		typedef ProjectileWeapon::GameModel BaseClass;

		// Time at which RTX has potential to jam (as measured on the m_cumulativeFiringTime member variable)
		Stuff::Scalar
			m_timeToPotentialJam;
		
		// Time at which RTX has will jam after reaching m_timeToJamPotential (as measured on the m_cumulativeFiringTime member variable)
		Stuff::Scalar
			m_timeToJam;
		
		// Time for which RTX will be unavailable after jamming
		Stuff::Scalar
			m_timeToUnjam;
/*		
		// Total time that the RTX has been firing continuously. Decremented at same rate as incremented when 
		//		RTX is inactive and not jammed
		Stuff::Scalar
			m_cumulativeFiringTime;

		// Total time that the RTX has been jammed; used as counter 
		Stuff::Scalar
			m_cumulativeJammedTime;
*/
		enum {
			TimeToPotentialJamAttributeID = ProjectileWeapon__GameModel::NextAttributeID,
			TimeToJamAttributeID,
			TimeToUnjamAttributeID,
			NextAttributeID
		};

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

		static void
			ConstructGameModel(Script *script);
	};

	//##########################################################################
	//###########################   RTXWeaponSub    ############################
	//##########################################################################


	class RTXWeaponSub:
		public ProjectileWeapon
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef RTXWeaponSub__ClassData							ClassData;
		typedef RTXWeaponSub__GameModel							GameModel;
		typedef RTXWeaponSub__Message							Message;
		typedef RTXWeaponSub__ExecutionStateEngine				ExecutionStateEngine;
		typedef RTXWeaponSub__CreateMessage						CreateMessage;

		typedef ProjectileWeapon								BaseClass;

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



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

		~RTXWeaponSub();

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

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


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Support
	//
	public:
		void
			CreateProjectile(Stuff::Time till);

		void
			PostCollisionExecute(Time till);

		void
			PreCollisionExecute(Time till);

		// johnyo Mercs bug 4712
		// This weapon needs to override this function. Unlike the normal projectile classes, this one requires that it
		// be able to fire while in the "recharging" state.
		//
		bool
			ReadyToFire();

		void 
			StartJamState();

/*
//
// johnyo Experimental code. Leaving in case this weapon needs tighter security. We'll need to add code to support
//			having the server shove it's jammed value to the client instead of relying on the client.
//

		bool 
			GetIsJammed() {return (executionState->GetState() == ExecutionStateEngine::JammedState || m_jamThisFrame);};

		void 
			SetJammed() {executionState->RequestState(ExecutionStateEngine::JammedState);return;};

*/	
	  // Time marker indicating the start of the RTX jam

		void
			Fire(Adept::Entity::CollisionQuery *query, 
				 Stuff::Time time_locked, 
				 const Stuff::Point3D& lockedTargetEntityPartOffset);


		Stuff::Time
			m_jamStartTime;

		// Last time that the player started firing the RTX 
		Stuff::Time
			m_fireStartTime;

		// Time at which the RTX stopped firing
		Stuff::Time
			m_fireEndTime;
		// Time we first entered recharge. Used to help minimize difference between server and client on what the
		// cumulative fire time is. Server enters recharge more often when packets aren't arriving faster than .25 seconds.
		Stuff::Time
			m_enterRecharge;

		bool 
			m_jamThisFrame;

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

	inline
		RTXWeaponSub__ExecutionStateEngine::RTXWeaponSub__ExecutionStateEngine(
			ClassData *class_data,
			RTXWeaponSub *mover,
			FactoryRequest *request
		):
			ProjectileWeapon__ExecutionStateEngine(class_data, mover, request)
	{
	}

}



