#pragma once

#include "vtvsub.h"
#include "..\munga\rotation.h"

//##########################################################################
//#####################    Chute::UpdateRecord         #####################
//##########################################################################

struct Chute__UpdateRecord :
	public VTVSubsystem::UpdateRecord
{
	Quaternion
		chuteDirection;
	Vector3D
		scaleFactor;
	int
		chuteOn;
};

//##########################################################################
//#####################    Chute::SubsystemResource    #####################
//##########################################################################

struct Chute__SubsystemResource:
	public VTVSubsystem::SubsystemResource
{
	int chuteCount;
	Scalar
		reloadTime,
		dragForce,
		minVelocity;

	Scalar
		deployTime;
	Scalar
		zDeviation;
};

//##########################################################################
//############################    Chute    ###############################
//##########################################################################

class Chute:
	public VTVSubsystem
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messageing Support
//
public:
	enum {
		ActivateMessageID = VTVSubsystem::NextMessageID,
		ConfigureMappablesMessageID,
		ChooseButtonMessageID,
		NextMessageID
	};

	void
		ActivateMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		ConfigureMappablesMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);
	void
		ChooseButtonMessageHandler(
			ReceiverDataMessageOf<ControlsButton> *message
		);

protected:

	static const HandlerEntry
		MessageHandlerEntries[];
	static MessageHandlerSet
		MessageHandlers;

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
	enum {
		TimeToReadyAttributeID = VTVSubsystem::NextAttributeID,
		ChutesRemainingAttributeID,
		ChuteDirectionAttributeID,
		ScaleFactorAttributeID,
		ChuteOnAttributeID,
		PercentDoneAttributeID,
		NextAttributeID
	};

private:
	static const IndexEntry AttributePointers[];

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

//
// public attribute declarations go here
//
public:
	Scalar
		timeToReady;
	Scalar
		chutesRemaining;
	Quaternion
		chuteDirection;
	Vector3D
		scaleFactor;
	int
		chuteOn;
	Scalar
		percentDone;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
	enum {
		Released = VTVSubsystem::StateCount,
		Deploy,
		Loading,
		Ready,
		Dragging,
		StateCount
	};
	typedef Chute__UpdateRecord UpdateRecord;

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

	void
		ChuteSimulation(Scalar time_slice);
	void
		PointChute(Scalar time_slice);

	void
		SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}

	VTV*
		GetEntity()
			{Check(this); return Cast_Object(VTV*, Subsystem::GetEntity());}

protected:
	void
		WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model);
	void
		ReadUpdateRecord(Simulation::UpdateRecord *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//   Damage Support
//
void
	DeathReset(int reset_command);
void
	DeathShutdown(int shutdown_command);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
	typedef Chute__SubsystemResource SubsystemResource;

	static int
		CreateStreamedSubsystem(
			NotationFile					*model_file,
			const char						*model_name,
			const char						*subsystem_name,
			SubsystemResource				*subsystem_resource,
			NotationFile					*subsystem_file,
			const ResourceDirectories	*directories
		);

	Chute(
		VTV *owner,
		int subsystem_ID,
		SubsystemResource *subsystem_resource
	);
	~Chute();

	Logical
  	TestInstance() const;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local data for the Chute class
//
private:
  int 		chuteCount;
	Scalar   reloadTime;
	Scalar   dragForce;
	Scalar	minVelocity;

	Point3D
		chuteOffset;

	Scalar
		deployTime,
		deployTimeUsed;

	Scalar
		zDeviation;

	void
		ApplyDrag(Scalar time_slice);

	int
		DeviantChute();

	void
		ReleaseChute();


	Scalar
		ScaleZ();

	Scalar
		ScaleXY();

};