#pragma once

#include "Mix/Scene/ILibertyCollider.h"
#include "Mix/Private/Scene/Common/DynamicsObject.h"

namespace Mix{ namespace Dynamics{
	class RigidBody;
}}

namespace Mix{ namespace Scene{ namespace Common{

	class LibertyCollider : public Mix::Scene::ILibertyCollider, public Mix::Scene::Common::DynamicsObject
	{
	private:
		Mix::Scene::IRendererObject* m_pOwner;
		Mix::Dynamics::RigidBody* m_pRigidBody;

	public:
		static LibertyCollider* CreateInstance( Mix::Scene::IRendererObject* pOwner );

	private:
		LibertyCollider( Mix::Scene::IRendererObject* pOwner );
		virtual ~LibertyCollider( void );

	public:
		Boolean Initialize( Mix::Dynamics::IShape* pShape, const wchar_t* pDebugName );

		void Dispose( void );

		Mix::Dynamics::IRigidBody* GetInternalRigidBodyPtr( void ) const;

	public:
		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::Common::DynamicsObject
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Mix::Dynamics::IObject* GetInternalObjectPtr( void ) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::ILibertyCollider
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Boolean IsSimulationEnabled( void ) const;
		virtual void SetSimulationEnabled( Boolean state );

		virtual Mix::Dynamics::IRigidBody::STATUS GetStatus( void ) const;
		virtual Boolean SetStatus( Mix::Dynamics::IRigidBody::STATUS status );

		virtual UInt16 GetFilterGroup( void ) const;
		virtual void SetFilterGroup( UInt16 filterGroup );

		virtual UInt16 GetFilterMask( void ) const;
		virtual void SetFilterMask( UInt16 filterMask );

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::IKineticCollider
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Float32 GetMass( void ) const;
		virtual void SetMass( Float32 mass );

		virtual const Mix::Dynamics::MATERIAL& GetMaterial( void ) const;
		virtual void SetMaterial( const Mix::Dynamics::MATERIAL& material );

		virtual Boolean IsAlwaysActive( void ) const;
		virtual Boolean SetAlwaysActive( Boolean state );

		virtual Boolean IsActive( void ) const;
		virtual Boolean Activate( void );
		virtual Boolean Deactivate( Boolean bFroce = False );

		virtual Mix::Vector3 GetLinearFactor( void ) const;
		virtual void SetLinearFactor( const Mix::Vector3& factor );

		virtual Float32 GetLinearDamping( void ) const;
		virtual void SetLinearDamping( Float32 damping );

		virtual Mix::Vector3 GetLinearVelocity( void );
		virtual Boolean SetLinearVelocity( const Mix::Vector3& velocity );

		virtual Float32 GetLinearSleepingThresholds( void ) const;
		virtual void SetLinearSleepingThresholds( Float32 thresholds );

		virtual Mix::Vector3 GetAngularFactor( void ) const;
		virtual void SetAngularFactor( const Mix::Vector3& factor );

		virtual Float32 GetAngularDamping( void ) const;
		virtual void SetAngularDamping( Float32 damping );

		virtual Mix::Vector3 GetAngularVelocity( void );
		virtual Boolean SetAngularVelocity( const Mix::Vector3& velocity );

		virtual Float32 GetAngularSleepingThresholds( void ) const;
		virtual void SetAngularSleepingThresholds( Float32 thresholds );

		virtual Boolean ApplyLinearImpulse( const Mix::Vector3& impulse );
		virtual Boolean ApplyAngularImpulse( const Mix::Vector3& impulse );
		virtual Boolean ApplyImpulse( const Mix::Vector3& impulse, const Mix::Vector3& pos );

		virtual Mix::Vector3 GetTotalLinearForce( void );
		virtual Mix::Vector3 GetTotalAngularForce( void );
		virtual Boolean ApplyLinearForce( const Mix::Vector3& force );
		virtual Boolean ApplyAngularForce( const Mix::Vector3& force );
		virtual Boolean ApplyForce( const Mix::Vector3& force, const Mix::Vector3& pos );
		virtual void ClearForce( void );

		virtual void ClearMotion( void );
		virtual void ClearMotion( const Mix::Quaternion& rot, const Mix::Vector3& pos );

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::ICollider
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Boolean IsDefault( void ) const;
		virtual Boolean IsStatic( void ) const;
		virtual Boolean IsKinematic( void ) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::IDynamicsObject
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Mix::Scene::IDynamicsObject::TYPE GetType( void ) const;

		virtual Boolean GetOwner( Mix::Scene::IRendererObject** ppOwner );
		virtual Mix::Scene::IRendererObject* GetOwnerPtr( void ) const;

		virtual Mix::Matrix4x4 GetWorldMatrix( void ) const;
		virtual Mix::Quaternion GetWorldRotation( void ) const;
		virtual Mix::Vector3 GetWorldPosition( void ) const;

		virtual Boolean HasContactListener( void ) const;
		virtual Boolean ContainsContactListener( Mix::Scene::IContactListener* pListener ) const;
		virtual Boolean AddContactListener( Mix::Scene::IContactListener* pListener );
		virtual Boolean RemoveContactListener( Mix::Scene::IContactListener* pListener );
		virtual void ClearContactListener( void );

		virtual Int32 GetUserIndex( void )  const;
		virtual void SetUserIndex( Int32 index );

		virtual void* GetUserPtr( void ) const;
		virtual void SetUserPtr( void* ptr );
	};

}}}
