#pragma once

#include "Mix/Dynamics/ISliderJoint.h"
#include "Mix/Private/Dynamics/Joint.h"

namespace Mix{ namespace Dynamics{

	class SliderJoint : public Mix::Dynamics::ISliderJoint, public Mix::Dynamics::Joint
	{
	private:
		enum PARAM_FLAG
		{
			PF_LL_LS	= 0x00000001,
			PF_LL_LD	= 0x00000002,
			PF_LL_OS	= 0x00000004,
			PF_LL_OD	= 0x00000008,

			PF_AL_LS	= 0x00000010,
			PF_AL_LD	= 0x00000020,
			PF_AL_OS	= 0x00000040,
			PF_AL_OD	= 0x00000080,
		};

	public:
		static SliderJoint* CreateInstance( Mix::Dynamics::IRigidBody* pRigidBodyA,
											const Mix::Quaternion& rotA,
											const Mix::Vector3& pivotA );

		static SliderJoint* CreateInstance( Mix::Dynamics::IRigidBody* pRigidBodyA,
											Mix::Dynamics::IRigidBody* pRigidBodyB,
											const Mix::Quaternion& rotA,
											const Mix::Quaternion& rotB,
											const Mix::Vector3& pivotA,
											const Mix::Vector3& pivotB );

	private:
		Mix::Dynamics::IRigidBody* m_pRigidBodyA;
		Mix::Dynamics::IRigidBody* m_pRigidBodyB;
		Mix::Quaternion m_RotA;
		Mix::Quaternion m_RotB;
		Mix::Vector3 m_PivotA;
		Mix::Vector3 m_PivotB;

		btSliderConstraint* m_pObject;

		UInt32 m_ParamFlags;

	private:
		SliderJoint(	Mix::Dynamics::IRigidBody* pRigidBodyA,
						const Mix::Quaternion& rotA,
						const Mix::Vector3& pivotA );

		SliderJoint(	Mix::Dynamics::IRigidBody* pRigidBodyA,
						Mix::Dynamics::IRigidBody* pRigidBodyB,
						const Mix::Quaternion& rotA,
						const Mix::Quaternion& rotB,
						const Mix::Vector3& pivotA,
						const Mix::Vector3& pivotB );

		virtual ~SliderJoint( void );

	public:
		Boolean Initialize( const wchar_t* pDebugName );

		void UpdateFrames( void );

	public:
		virtual Mix::Dynamics::IJoint::TYPE GetType( void ) const;

		virtual Boolean IsInWorld( void ) const;

		virtual Boolean IsEnabled( void ) const;
		virtual void SetEnabled( Boolean state );

		virtual Float32 GetBreakingImpulseThreshold( void ) const;
		virtual void SetBreakingImpulseThreshold( Float32 threshold );

		virtual Boolean IsSingle( void ) const;

		virtual void GetRigidBodyA( Mix::Dynamics::IRigidBody** ppRigidBody );
		virtual void GetRigidBodyB( Mix::Dynamics::IRigidBody** ppRigidBody );

		virtual const Mix::Vector3& GetPivotA( void ) const;
		virtual void SetPivotA( const Mix::Vector3& pivot );

		virtual const Mix::Vector3& GetPivotB( void ) const;
		virtual void SetPivotB( const Mix::Vector3& pivot );

	public:
		virtual UInt32 Debug_GetDrawFlags( void ) const;
		virtual void Debug_SetDrawFlags( UInt32 flags );

		virtual Float32 Debug_GetDrawFrameMinSize( void ) const;
		virtual void Debug_SetDrawFrameMinSize( Float32 minSize );

		virtual Float32 Debug_GetDrawLimitScaling( void ) const;
		virtual void Debug_SetDrawLimitScaling( Float32 scaling );

		virtual void Debug_Draw( Mix::Graphics::Utility::IPerspectiveRenderer* pPerspectiveRenderer, Float32 opacity );

	public:
		virtual const Mix::Quaternion& GetRotationA( void ) const;
		virtual void SetRotationA( const Mix::Quaternion& rot );

		virtual const Mix::Quaternion& GetRotationB( void ) const;
		virtual void SetRotationB( const Mix::Quaternion& rot );

		virtual void SetLinearLimit( Float32 lower, Float32 upper );
		virtual Float32 GetLinearLowerLimit( void ) const;
		virtual Float32 GetLinearUpperLimit( void ) const;

		virtual void SetAngularLimit( Float32 lower, Float32 upper );
		virtual Float32 GetAngularLowerLimit( void ) const;
		virtual Float32 GetAngularUpperLimit( void ) const;

		virtual Boolean GetLinearMotorEnabled( void ) const;
		virtual void SetLinearMotorEnabled( Boolean state );
		virtual Float32 GetLinearMotorTargetVelocity( void ) const;
		virtual void SetLinearMotorTargetVelocity( Float32 tv );
		virtual Float32 GetLinearMotorMaxForce( void ) const;
		virtual void SetLinearMotorMaxForce( Float32 mf );

		virtual Boolean GetAngularMotorEnabled( void ) const;
		virtual void SetAngularMotorEnabled( Boolean state );
		virtual Float32 GetAngularMotorTargetVelocity( void ) const;
		virtual void SetAngularMotorTargetVelocity( Float32 tv );
		virtual Float32 GetAngularMotorMaxForce( void ) const;
		virtual void SetAngularMotorMaxForce( Float32 mf );

		virtual Float32 GetLinearLimit_LimSpring( void ) const;
		virtual void SetLinearLimit_LimSpring( Float32 spring );
		virtual Float32 GetLinearLimit_LimDamper( void ) const;
		virtual void SetLinearLimit_LimDamper( Float32 damper );
		virtual Float32 GetLinearLimit_OrthoSpring( void ) const;
		virtual void SetLinearLimit_OrthoSpring( Float32 spring );
		virtual Float32 GetLinearLimit_OrthoDamper( void ) const;
		virtual void SetLinearLimit_OrthoDamper( Float32 damper );

		virtual Float32 GetAngularLimit_LimSpring( void ) const;
		virtual void SetAngularLimit_LimSpring( Float32 spring );
		virtual Float32 GetAngularLimit_LimDamper( void ) const;
		virtual void SetAngularLimit_LimDamper( Float32 damper );
		virtual Float32 GetAngularLimit_OrthoSpring( void ) const;
		virtual void SetAngularLimit_OrthoSpring( Float32 spring );
		virtual Float32 GetAngularLimit_OrthoDamper( void ) const;
		virtual void SetAngularLimit_OrthoDamper( Float32 damper );

	public:
		virtual btTypedConstraint* Bullet_GetTypedConstraintPtr( void ) const;

	public:
		static const wchar_t* FAILED_CREATE;
	};

}}
