//===========================================================================//
// File:	Torso.hpp													
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/12/99  DPB  Created File
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#pragma once

#include "MW4.hpp"
#include "Subsystem.hpp"

namespace MechWarrior4
{
	class Vehicle;
	class MWMover;
	class Torso__GameModel;

	//##########################################################################
	//###########################   Torso    ###################################
	//##########################################################################

	typedef Subsystem__ClassData									Torso__ClassData;
	typedef Subsystem__Message										Torso__Message;
	typedef Subsystem__ExecutionStateEngine					Torso__ExecutionStateEngine;
	typedef Subsystem__CreateMessage								Torso__CreateMessage;


	class Torso__GameModel:
		public Subsystem::GameModel
	{
	public:

		char 
			twistJointName[MaxStringLength],
			pitchJointName[MaxStringLength],
			leftArmJointName[MaxStringLength],
			rightArmJointName[MaxStringLength],
			eyeJointName[MaxStringLength],
			cageJointName[MaxStringLength];

		Stuff::Scalar
			twistSpeed;
		Stuff::Scalar
			pitchSpeed;

		Stuff::Scalar
			twistRadius;
		Stuff::Scalar
			pitchRadius;

		Stuff::Scalar
			armRatioAngle;

		Stuff::Scalar
			cageRatioAngle;

		enum {
			TwistSpeedAttributeID = Subsystem__GameModel::NextAttributeID,
			PitchSpeedAttributeID,
			TwistRadiusAttributeID,
			PitchRadiusAttributeID,
			TwistJointNameAttributeID,
			PitchJointNameAttributeID,
			LeftArmJointNameAttributeID,
			RightArmJointNameAttributeID,
			EyeJointNameAttributeID,
			ArmRatioAngleAttributeID,
			CageJointNameAttributeID,
			CageRatioAngleAttributeID,
			NextAttributeID
		};

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

		static void
			ConstructGameModel(Script *script);
	};

	//##########################################################################
	//########################     TorsoSubsystem    ###########################
	//##########################################################################

	class Torso:
		public Subsystem
	{
	public:
		static void
			InitializeClass();
		static void
			TerminateClass();

	//##########################################################################
	// Inheritance support
	//
	public:
		typedef Torso__ClassData								ClassData;
		typedef Torso__GameModel								GameModel;
		typedef Torso__Message									Message;
		typedef Torso__ExecutionStateEngine					ExecutionStateEngine;
		typedef Torso__CreateMessage							CreateMessage;


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

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

		~Torso();

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

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

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

		void
			SetTwistRotation();
		void
			SetPitchRotation();
		void
			SetPitchRotationSpecial();
		void
			SetRotation();
		bool
			ConnectSubsystem();
		void
			SetInternal(){internalTorso = true;};
		void
			SetExternal(){internalTorso = false;};
		void
			SetHeatMultiplier(Stuff::Scalar value);

		const Stuff::LinearMatrix4D&
			GetTwistJointMatrix();
		const Stuff::LinearMatrix4D&
			GetPitchJointMatrix();
		Stuff::Scalar
			GetTwistSpeed();
		Stuff::Scalar
			GetPitchSpeed();
		int 
			GetLookDirection() {return lookDirection;}

		MWMover
			*twistJoint;
		MWMover
			*pitchJoint;
		MWMover
			*rotationJoint;
		MWMover
			*leftArmJoint;
		MWMover
			*rightArmJoint;
		MWMover
			*eyeJoint;
		MWMover
			*cageJoint;


		Stuff::Scalar
			yawValue;
		Stuff::Scalar
			pitchValue;


		
		Stuff::Scalar
			oldYawValue;
		Stuff::Scalar
			oldPitchValue;
		Stuff::Scalar
			yawValueCorrection;
		Stuff::Scalar
			pitchValueCorrection;
		Stuff::Scalar
			correctionTime;
		Stuff::Scalar
			correctionCurTime;


		Stuff::Scalar
			lookTypeVerticalAdjust; 
		Stuff::Scalar
			eyeYaw;
		Stuff::Scalar
			eyePitch;

		Stuff::Scalar
			eyeTransitionEndTime;
			
		Stuff::Scalar
			yawDemand;
		Stuff::Scalar
			pitchDemand;

		Stuff::Time
			surrender_time;

		Stuff::Scalar
			heatMultiplier;
		
		bool
			internalTorso;
		
		void
			PitchToPoint(const Stuff::Point3D& point);

		

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Arm Twist to side
	//
		enum {
			LookForwardDirection = 0,
			LookLeftDirection,
			LookRightDirection,
			LookBackDirection,
			LookDownDirection,
			SurrenderDirection
		};

		int lookDirection;


		enum {
			ForwardTwistState,
			SideTwistState,
			RearTwistState,
			ToRearTwistState,
			ToSideTwistState,
			ToForwardTwistState,
			
		};

		enum {
			ForwardPitchState,
			SurrenderPitchState,
			ToSurrenderState,
			ToForwardPitchState
		};

		

		int leftArmTwistState;
		int rightArmTwistState;
		int armPitchState;


		Stuff::Scalar armTwistTime;
		Stuff::Scalar armPitchTime;
		Stuff::Scalar leftArmTwistTimer;
		Stuff::Scalar rightArmTwistTimer;
		Stuff::Scalar pitchArmTwistTimer;

		Stuff::Scalar
			leftArmYaw;
		Stuff::Scalar
			rightArmYaw;
		Stuff::Scalar
			armPitch;


		void TurnArms(Stuff::Scalar time_slice);

		void LookLeft();
		void LookRight();
		void LookBack();
		void LookDown();
		void LookForward();
		void LookSurrender();

		Stuff::Point3D torsoRequest;			// for the torso movement
		bool followTorsoRequest;				// true if track torsoRequest point

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


