#pragma once

#include "Mix/Tool/Win32/Core/Dynamics/KinematicCharacter.h"
#include "LinearMath/btMatrix3x3.h"

class btCapsuleShape;
class btPairCachingGhostObject;
class btKinematicCharacterController;

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{ namespace Impl{

	class World;

	class KinematicCharacter : public Mix::Tool::Win32::Dynamics::KinematicCharacter
	{
	private:
		Mix::Tool::Win32::Dynamics::Impl::World* m_pWorld;

		btCapsuleShape* m_pShape;
		btPairCachingGhostObject* m_pGhostObject;
		btKinematicCharacterController* m_pCharacterController;

		Mix::Tool::Win32::Dynamics::MATERIAL m_Material;

		float m_Radius;
		float m_Height;
		float m_Gravity;
		float m_MaxFallSpeed;
		float m_InitJumpSpeed;
		float m_StepOffset;
		float m_SlopeLimit;

		D3DXVECTOR3 m_LinearVelocity;

		short m_Group;
		short m_GroupMask;

		D3DXQUATERNION m_Rot;
		btMatrix3x3 m_Basis;

	public:
		KinematicCharacter( void );
		virtual ~KinematicCharacter( void );

		bool Initialize( void );

		void SetWorldPtr( Mix::Tool::Win32::Dynamics::Impl::World* pWorld );

		btPairCachingGhostObject* Bullet_GetGhostObjectPtr( void );
		btKinematicCharacterController* Bullet_GetCharacterControllerPtr( void );

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

		virtual void SetHeight( float height );
		virtual float GetHeight( void ) const;

		virtual void SetRadius( float radius );
		virtual float GetRadius( void ) const;

		virtual void SetGravity( float gravity );
		virtual float GetGravity( void ) const;

		virtual void SetMaxFallSpeed( float speed );
		virtual float GetMaxFallSpeed( void ) const;

		virtual void SetInitJumpSpeed( float speed );
		virtual float GetInitJumpSpeed( void ) const;

		virtual void SetStepOffset( float stepOffset );
		virtual float GetStepOffset( void ) const;

		virtual void SetSlopeLimit( float slopeLimit );
		virtual float GetSlopeLimit( void ) const;

		virtual void SetLinearVelocity( const D3DXVECTOR3& vel );
		virtual const D3DXVECTOR3& GetLinearVelocity( void ) const;

		virtual bool IsGround( void ) const;

		virtual void Jump( void );

	public:
		virtual void SetGroup( short data );
		virtual short GetGroup( void ) const;

		virtual void SetGroupMask( short data );
		virtual short GetGroupMask( void ) const;

		virtual D3DXQUATERNION GetWorldRotation( void ) const;
		virtual void SetWorldRotation( const D3DXQUATERNION& rot );

		virtual D3DXVECTOR3 GetWorldPosition( void ) const;
		virtual void SetWorldPosition( const D3DXVECTOR3& pos );

		virtual D3DXMATRIX GetWorldMatrix( void ) const;
		virtual void SetWorldMatrix( const D3DXMATRIX& mat );

		virtual void SetWorldTransform( const D3DXQUATERNION& rot, const D3DXVECTOR3& pos );

		virtual bool IsInWorld( void ) const;

		virtual void Draw( Mix::Tool::Win32::Graphics::LineHelper* pLineHelper, const D3DXVECTOR4& color );

	private:
		static const float DEF_STEPOFFSET;
		static const float MIN_LINEAR_VELOCITY_Y;

		void BeginRefresh( void );
		void EndRefresh( void );
		bool Refresh( void );

		friend class Factory;
	};

}}}}}
