#pragma once

#include <set>
#include "Mix/Tool/Win32/Core/Dynamics/World.h"
#include "btBulletDynamicsCommon.h"

struct btDbvtBroadphase;

class btCollisionDispatcher;
class btSequentialImpulseConstraintSolver;
class btDefaultCollisionConfiguration;
class btDiscreteDynamicsWorld;
class btGhostPairCallback;
class btPoint2PointConstraint;

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

	class RigidBody;

	class World : public Mix::Tool::Win32::Dynamics::World
	{
	private:
		typedef std::set<Mix::Tool::Win32::Dynamics::CollisionObject*> CollisionObjectList;
		typedef std::set<Mix::Tool::Win32::Dynamics::Joint*> JointList;

	private:
		btCollisionDispatcher* m_pDispatcher;
		btDbvtBroadphase* m_pBroadphas;
		btSequentialImpulseConstraintSolver* m_pSolver;
		btDefaultCollisionConfiguration* m_pConfiguration;
		btDiscreteDynamicsWorld* m_pWorld;
		btGhostPairCallback* m_pGhostPairCallback;

		float m_PickPreDist;
		btPoint2PointConstraint* m_pPick;
		Mix::Tool::Win32::Dynamics::Impl::RigidBody* m_pPickRigidBody;

		World::CollisionObjectList m_CollisionObjectList;
		World::JointList m_JointList;

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

		bool Initialize( void );

		virtual void SetGravity( const D3DXVECTOR3& gravity );
		virtual D3DXVECTOR3 GetGravity( void );

		virtual bool AddCollisionObject( Mix::Tool::Win32::Dynamics::CollisionObject* pCollisionObject );
		virtual bool RemoveCollisionObject( Mix::Tool::Win32::Dynamics::CollisionObject* pCollisionObject );

		virtual bool AddJoint( Mix::Tool::Win32::Dynamics::Joint* pJoint );
		virtual bool RemoveJoint( Mix::Tool::Win32::Dynamics::Joint* pJoint );

		virtual void Picker_Catch( const D3DXVECTOR3& eyePos, const D3DXVECTOR3& fromWorldPos, const D3DXVECTOR3& toWorldPos );
		virtual void Picker_Update( const D3DXVECTOR3& eyePos, const D3DXVECTOR3& toWorldPos );
		virtual void Picker_Release( void );

		virtual void Update( float dt );

		virtual void Draw(	Mix::Tool::Win32::Graphics::LineHelper* pLineHelper,
							const D3DXVECTOR4& collObjColor,
							const D3DXVECTOR4& jointAxisColor,
							const D3DXVECTOR4& jointPivotColor,
							const D3DXVECTOR4& jointLimitColor );

	public:
		void AttachCollisionObject( Mix::Tool::Win32::Dynamics::CollisionObject* pCollisionObject, bool bSetWorldPtr = true );
		void DetachCollisionObject( Mix::Tool::Win32::Dynamics::CollisionObject* pCollisionObject, bool bSetWorldPtr = true );

		void AttachJoint( Mix::Tool::Win32::Dynamics::Joint* pJoint, bool bSetWorldPtr = true );
		void DetachJoint( Mix::Tool::Win32::Dynamics::Joint* pJoint, bool bSetWorldPtr = true );

	private:
		static bool CustomMaterialCombinerCallback( btManifoldPoint& cp,
													const btCollisionObjectWrapper* cow0, int partId0, int index0,
													const btCollisionObjectWrapper* cow1, int partId1, int index1 );
	};

}}}}}
