#include "rp.h"
#pragma hdrstop

#include "vtvpwr.h"
#include "thruster.h"
#include "vtv.h"

//#############################################################################
// Shared Data Support
//
VTVPower::SharedData
	VTVPower::DefaultData(
		VTVPower::GetClassDerivations(),
		VTVPower::GetMessageHandlers(),
		VTVPower::GetAttributeIndex(),
		VTVPower::StateCount
	);

Derivation* VTVPower::GetClassDerivations()
{
	static Derivation classDerivations(Subsystem::GetClassDerivations(), "VTVPower");
	return &classDerivations;
}

//#############################################################################
// Attribute Support
//
const VTVPower::IndexEntry
	VTVPower::AttributePointers[]=
{
	ATTRIBUTE_ENTRY(VTVPower, MaxAccelerationOutput, maxAccelerationOutput)
};

VTVPower::AttributeIndexSet& VTVPower::GetAttributeIndex()
{
	static VTVPower::AttributeIndexSet attributeIndex(ELEMENTS(VTVPower::AttributePointers),
		VTVPower::AttributePointers,
		Subsystem::GetAttributeIndex()
	);
	return attributeIndex;
}

//#############################################################################
// Model Support
//
void
	VTVPower::PowerSimulation(Scalar)
{
	Check(this);

	//
	//--------------------------------------------------------------------------
	// Get pointers to the other subsystems we will have to deal with inside the
	// VTV
	//--------------------------------------------------------------------------
	//
	VTV* vtv = GetEntity();
	Check(vtv);
	Scalar average_moment_arm = 0.0f;

	//
	//---------------------------------------
	// Find out the average moment arm length
	//---------------------------------------
	//
	JointSubsystem *joint_subsystem = vtv->GetJointSubsystem();
	Check(joint_subsystem);
	Verify(joint_subsystem->GetJointCount());

	int i;
	for (i=0; i<MAX_THRUSTERS; ++i)
	{
		Thruster* thruster =
			(Thruster*) vtv->GetSubsystem(VTV::Thruster1Subsystem + i);

		if(thruster != NULL)
		{
			average_moment_arm += thruster->momentArmLength;
		}
	}
	average_moment_arm /= joint_subsystem->GetJointCount();
	Scalar average_accel = maxAccelerationOutput / joint_subsystem->GetJointCount();
	Check_Fpu();

	for (i=0; i<MAX_THRUSTERS; ++i)
	{
		Thruster* thruster =
			(Thruster*) vtv->GetSubsystem(VTV::Thruster1Subsystem + i);

		if(thruster != NULL)
		{
			Check(thruster);
			Verify(!Small_Enough(thruster->momentArmLength));
			thruster->powerScale = average_moment_arm / thruster->momentArmLength;
			thruster->currentAcceleration = average_accel * thruster->powerScale;
		}
	}
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VTVPower::VTVPower(
	VTV *entity,
	int subsystem_ID,
	SubsystemResource *subsystem_resource
):
	Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData)
{
	if (entity->GetInstance() != VTV::ReplicantInstance)
	{
		SetPerformance(&VTVPower::PowerSimulation);
	}

	maxAccelerationOutput = subsystem_resource->maxAcceleration;
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VTVPower::~VTVPower()
{
	Check(this);
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	VTVPower::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}

