#pragma once

#include "..\munga\jmover.h"
#include "..\munga\vector2d.h"
#include "..\munga\controls.h"
#include "..\munga\normal.h"
#include "..\munga\damage.h"
#include "..\munga\reticle.h"
#include "rptool.h"

class VTVControlsMapper;
class VTV;
class RPPlayer;

#define ZIPPY 2.3f
#define MAX_THRUSTERS 6
//##########################################################################
//####################    VTV::DamageZone       ############################
//##########################################################################

class VTV__DamageZone :
	public DamageZone
{
	public:
		VTV__DamageZone(
			VTV *vtv,
        int damage_zone_index,
			MemoryStream *damage_zone_stream
		);

		static Logical
			CreateStreamedDamageZone(
				NotationFile					*model_file,
				const char						*model_name,
				NotationFile					*skl_file,
				const char						*damage_zone_name,
				MemoryStream					*damage_zone_stream,
				NotationFile					*dmg_file,
				const ResourceDirectories	*directories
			);

		void
			TakeDamage(Damage& damage);

};

//##########################################################################
//####################    VTV::UpdateMessage    ############################
//##########################################################################

struct VTV__UpdateRecord:
	public JointedMover::UpdateRecord
{
public:
	Enumeration
		collisionState,
		collisionMaterialType;
	Normal
		collisionNormal;
	Scalar
		collisionSpeed;
	Logical
		boosterOn;
	Vector3D
		boosterScale;
	Scalar
		boosterSmokeDensity;
	int
		hornBlast; // HACK - ECH 7/31/95 - For replicants
};

//##########################################################################
//######################    VTV::ModelResource    ##########################
//##########################################################################

struct VTV__ModelResource:
	public JointedMover::ModelResource
{

	Scalar
		maxAcceleration,
		groundEffectDomainSquared,
		groundEffectRange,
		maxThrusterRotationRate,
		maxYawVelocity,
		angularSpringFactor,
		bankFactor,
		deathSpeed,
		deathScoreLoss,
		maxImpactSpeed,
		bottomArmorScale,
		powerDive;

	Vector3D
		maxAngularAcceleration;

	int
		jointIndex[MAX_THRUSTERS],
		segmentIndex[MAX_THRUSTERS];

	Reticle::ModelResource
		reticleResource;
};

//##########################################################################
//#####################    Mover::MakeMessage    ##########################
//##########################################################################

class VTV__MakeMessage:
	public JointedMover::MakeMessage
{
public:
	char
		vehicleBadge[20],
		vehicleColor[20];

	VTV__MakeMessage(
		Receiver::MessageID message_ID,
		size_t length,
		Entity::ClassID class_ID,
		const EntityID &owner_ID,
		ResourceDescription::ResourceID resource_ID,
		LWord instance_flags,
		const Origin &origin,
		const Motion &velocity,
		const Motion &acceleration,
		const char* badge,
		const char* color
	):
		JointedMover::MakeMessage(
			message_ID,
			length,
			class_ID,
			owner_ID,
			resource_ID,
			instance_flags,
			origin,
			velocity,
			acceleration
		)
			{
				Str_Copy(vehicleBadge, badge, sizeof(vehicleBadge));
				Str_Copy(vehicleColor, color, sizeof(vehicleColor));
			}

	VTV__MakeMessage(
		Receiver::MessageID message_ID,
		size_t length,
		const EntityID &entity_ID,
		Entity::ClassID class_ID,
		const EntityID &owner_ID,
		ResourceDescription::ResourceID resource_ID,
		LWord instance_flags,
		const Origin &origin,
		const Motion &velocity,
		const Motion &acceleration,
		const char* badge,
		const char* color
	):
		JointedMover::MakeMessage(
			message_ID,
			length,
			entity_ID,
			class_ID,
			owner_ID,
			resource_ID,
			instance_flags,
			origin,
			velocity,
			acceleration
		)
			{
				Str_Copy(vehicleBadge, badge, sizeof(vehicleBadge));
				Str_Copy(vehicleColor, color, sizeof(vehicleColor));
			}
};

//##########################################################################
//#############################    VTV    ##################################
//##########################################################################

class VTV:
	public JointedMover
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
	static Derivation *GetClassDerivations();
	static SharedData DefaultData;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
	enum {
		KavorkianMessageID = JointedMover::NextMessageID,
		MarkSpotMessageID,
		RestoreToSpotMessageID,
		ZoomInMessageID,
		ZoomOutMessageID,
		NextMessageID
	};

private:
	static const HandlerEntry MessageHandlerEntries[];

protected:
	static MessageHandlerSet MessageHandlers;

	void
		TakeDamageMessageHandler(TakeDamageMessage *message);
	void
		ZoomInMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		ZoomOutMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		KavorkianMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		MarkSpotMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		RestoreToSpotMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);

	void
		PlayerLinkMessageHandler(PlayerLinkMessage *message);

	Origin savedOrigin;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
	enum {
		HeightAboveTerrainAttributeID = JointedMover::NextAttributeID,
		ThrusterPitchAttributeID,
		CollisionStateAttributeID,
		CollisionMaterialTypeAttributeID,
		CollisionNormalAttributeID,
		CollisionSpeedAttributeID,
		EyepointRotationAttributeID,
		BoosterOnAttributeID,
		BoosterScaleAttributeID,
		BoosterSmokeDensityAttributeID,
		ForwardVelocityAttributeID,
		CompassHeadingAttributeID,
		TargetReticleAttributeID,
		NavigationRangeAttributeID,
		NavigationLinearPositionAttributeID,
		NavigationAngularPositionAttributeID,
		ScoreStateAttributeID,
		ScoreTypeAttributeID,
		HornBlastAttributeID, // HACK - ECH 7/31/95 - For replicants
		NextAttributeID
	};

	virtual Vector3D
		GetWorldLinearVelocity()
     	{return worldLinearVelocity;}

private:
	static const IndexEntry AttributePointers[];

protected:
	//static AttributeIndexSet	AttributeIndex
	static AttributeIndexSet& GetAttributeIndex();

//
// public attribute declarations go here
//
public:
	int hornBlast; // HACK - ECH 7/31/95 - For replicants
	Scalar heightAboveTerrain;
	Hinge thrusterPitch;
	EulerAngles eyepointRotation;
	Logical boosterOn;
	Vector3D boosterScale;
	Scalar boosterSmokeDensity;
	Scalar forwardVelocity;
	YawPitchRoll compassHeading;
	Reticle targetReticle;

	Scalar navigationRange;
	Point3D
		*navigationLinearPosition;	// ptr to linear pos of object or NULL
	Quaternion
		*navigationAngularPosition;	// ptr to angular pos of object or NULL

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model support
//
public:
	enum {
		BurningState = JointedMover::StateCount,
		StateCount
	};

	enum {
		ControlsMapperSubsystem,
		PowerSubsystem,
		Thruster1Subsystem,
		Thruster2Subsystem,
		Thruster3Subsystem,
		Thruster4Subsystem,
		Thruster5Subsystem,
		Thruster6Subsystem,
		JointSubsystemID,
		BasicSubsystemCount
	};

	typedef void
		(VTV::*Performance)(Scalar time_slice);

	void
		SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}
	void
		SetMappingSubsystem(VTVControlsMapper *mapper);

	void
		MoveAndCollide(Scalar time_slice);

	Logical
		BoosterOn();

protected:
	typedef VTV__UpdateRecord UpdateRecord;

	void
		WriteUpdateRecord(
			Simulation::UpdateRecord *message,
			int update_model
		);
	void
		ReadUpdateRecord(Simulation::UpdateRecord *message);

public:
	Scalar
		groundEffectDomainSquared,
		groundEffectRange,
		angularSpringFactor,
		bankFactor,
		maxYawVelocity,
		powerDive,
		thrusterAngle;
	Vector3D
		maxAngularAcceleration;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Collision support
//
public:
	enum {
		NoCollisionState = 0,
		InitialHitState,
		SlideState,
		RestState,
		CollisionStateCount
	};

	Enumeration
		collisionTemporaryState;
	StateIndicator
		collisionState;
	Enumeration
		collisionMaterialType;
	Normal
		collisionNormal;
	Scalar
		collisionSpeed,
		bottomArmorScale;

protected:
	void
		PerformAndWatch(
			const Time& till,
			MemoryStream *update_stream
		);

	void
		ProcessCollision(
			Scalar time_slice,
			BoxedSolidCollision &collision,
			const Point3D &old_position,
			Damage *damage
		);

	Time
		lastDoorHit;
	Vector3D
		doorHitNormal;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Damage support
//
public:
	Scalar
		deathSpeed,
		deathScoreLoss;

	Scalar
		deathConstant;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Scoring support
//
public:
	//
  // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score
  // messages, allows attribute system to be used for scoring
  //
  void
  	RespondToScoreMessage(Message *message);

	StateIndicator
		scoreState;

  Enumeration
		scoreType;

	Logical
		insideWorld;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
	typedef VTV__ModelResource ModelResource;
	typedef VTV__MakeMessage MakeMessage;
  typedef VTV__DamageZone	DamageZone;

	static VTV*
		Make(MakeMessage *creation_message);

	static ResourceDescription::ResourceID
		CreateModelResource(
			ResourceFile *resource_file,
			const char *model_name,
			NotationFile *model_file,
			const ResourceDirectories *directories,
			ModelResource* model=NULL
		);
	static ResourceDescription::ResourceID
		CreateSubsystemStream(
			ResourceFile *resource_file,
			const char *model_name,
			NotationFile *model_file,
			const ResourceDirectories *directories
		);
	static ResourceDescription::ResourceID
		CreateDamageZoneStream(
			ResourceFile 	*resource_file,
			const char 		*dzone_name,
			NotationFile 	*dmg_file,
			const ResourceDirectories *directories
		);
	typedef Logical
		(*FindNameFunction)(
			const char *control_name,
			ControlsMapping *mapping
		);
	static Simulation::SharedData*
		GetSubsystemSharedData(const char *name);

	static ResourceDescription::ResourceID
		CreateControlMappingStream(
			const char *mapping_name,
			NotationFile *mapping_file,
			FindNameFunction find_name,
			ResourceFile *resource_file,
			const char *model_name,
			NotationFile *model_file,
			const ResourceDirectories *directories,
			PlatformTool *current_tool
		);

	VTV(
		MakeMessage *creation_message,
		SharedData &virtual_data = DefaultData
	);
	~VTV();

	Logical
  	TestInstance() const;

	enum {
		RegularReset,
		FootballReset,
		MissionReviewReset
	};

	void
		Reset(const Origin &new_origin, int reset_command);

	void
		DeathShutdown(int shutdown_command);

	char
		vehicleBadge[20],
		vehicleColor[20];

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Navigation support
protected:
	Scalar
		targetRangeExponent,
		currentRangeExponent;
public:

	Scalar
  	maxImpactSpeed;
};
