//===========================================================================//
// File:	DeceleratorOf.hpp                                                 
// Project: MechWarrior 4
// Contents: 
//			AngleAxis class for animation.  This is just an unlimited rotation
//	quaternion
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 06/02/99  JSE  Initial coding, 
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive, Inc.
// All Rights reserved worldwide
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL
//===========================================================================//

#pragma once

namespace MechWarrior4 {


	//##########################################################################
	//#########################    DeceleratorOf    ###############################
	//##########################################################################
	
	template <class T> class DeceleratorOf
	{
	public:
		
		T motionLimit;

		T motionDecceleration;
		T returnForce;
		T outwardForce;

		T homePosition;
		T currentPosition;
		T currentSpeed;

		bool initialized;

		DeceleratorOf()
		{
			initialized = false;
		}

		DeceleratorOf(T motion_limit, T motion_acceleration, T return_speed, T home_position, T outward_force)
		{
			Initialize(motion_limit, motion_acceleration, return_speed, home_position, outward_force);
		};

		~DeceleratorOf(){};

		void Initialize(T motion_limit, T motion_decceleration, T return_force, T home_position, T outward_force)
		{
			initialized = true;
			motionLimit = motion_limit;
			motionDecceleration = motion_decceleration;
			returnForce = return_force;
			homePosition = home_position;
			currentPosition = homePosition;
			outwardForce = outward_force;

			for (int i = 0; i < T::GetMemberCount(); i++)
			{
				currentSpeed[i] = 0.0f;
			}
		};
	
		// 0 to 1, 1 being full stretch of the spring.
		void SetInitialSpeed(T how_hard)
		{
			Verify(initialized);

			T new_speed;
			for (int i = 0; i < T::GetMemberCount(); i++)
			{
				new_speed[i] = outwardForce[i] * how_hard[i];
			}
			
			for (i = 0; i < T::GetMemberCount(); i++)
			{
				currentSpeed[i] = new_speed[i] + currentSpeed[i];
			}

		}

		void StopAndGoHome(void)
		{
			
			for (int i = 0; i < T::GetMemberCount(); i++)
			{
				if (currentSpeed[i] > 0.0f)
				{
					currentSpeed[i] = returnForce[i];
				}
			}

		}

		void Reset(void)
		{
			for (int i = 0; i < T::GetMemberCount(); i++)
			{
				currentSpeed[i] = 0;
			}
			currentPosition = homePosition;
		}

		T GetCurrentPosition(void)
		{
			return currentPosition;
		};

		
		void AdvanceTime(Stuff::Scalar time_slice)
		{
		
			Verify(initialized);

			for (int i = 0; i < T::GetMemberCount(); i++)
			{
				
			
				if (currentSpeed[i] > 0.0f)
				{
					currentSpeed[i] -= (motionDecceleration[i] * time_slice);
					Min_Clamp(currentSpeed[i], 0.0f);

					currentPosition[i] += (currentSpeed[i] * time_slice);
					Max_Clamp(currentPosition[i], motionLimit[i]);

					if (currentPosition[i] >= motionLimit[i])
					{
						currentPosition[i] = motionLimit[i];
						currentSpeed[i] = 0.0f;
					}

				}
				else if (currentSpeed[i] < 0.0f)
				{
					currentSpeed[i] += (motionDecceleration[i] * time_slice);
					Max_Clamp(currentSpeed[i], 0.0f);

					currentPosition[i] += (currentSpeed[i] * time_slice);
					

					if (currentPosition[i] <= -motionLimit[i])
					{
						currentPosition[i] = -motionLimit[i];
						currentSpeed[i] = 0.0f;
					}

				}

				if (currentSpeed[i] == 0.0f)
				{
					if (currentPosition[i] > homePosition[i])
					{
						currentPosition[i] -= returnForce[i] * time_slice;
						Min_Clamp(currentPosition[i], homePosition[i]);
					}
					else if (currentPosition[i] < homePosition[i])
					{
						currentPosition[i] += returnForce[i] * time_slice;
						Max_Clamp(currentPosition[i], homePosition[i]);
					}
				}
			}
		}
	};

}

