#ifndef INCLUDED_PHYSICS_WORLD
#define INCLUDED_PHYSICS_WORLD

#include <Math/Vector.h>

#include <functional>
#include <memory>
#include <list>

class btDiscreteDynamicsWorld;
class btSequentialImpulseConstraintSolver;
class btBroadphaseInterface;
class btCollisionDispatcher;
class btDefaultCollisionConfiguration;

//////////////////////////////////////////////////////////////
namespace Dubious {
namespace Physics {

class PhysicalObject;
typedef std::shared_ptr<PhysicalObject> PhysicalObjectPtr;
typedef std::list<PhysicalObjectPtr> PhysicalObjectPtrList;

/// @brief The main container for the Physics Engine
///
/// Sort of like the Scene is to the renderer, the World collects
/// all of the physical objects in the app.  It's basically just a 
/// thin wrapper around the btDiscreteDynamicsWorld
class World
{
public:
	World();
	~World();

	void                StepSimulation( float Elapsed, unsigned int &Bullet, unsigned int &Maint, unsigned int &Handling );
	void                AddObject( PhysicalObjectPtr pObject );
	void                RemoveObject( PhysicalObjectPtr pObject );
	void                SetGravity( const Math::Vector& Gravity );
	void				RemoveAllObjects();

	std::function<void (PhysicalObjectPtr pA, PhysicalObjectPtr pB)>& OnCollision() { return m_OnCollision; }

private:
	std::function<void (PhysicalObjectPtr pA, PhysicalObjectPtr pB)> m_OnCollision;

	btDiscreteDynamicsWorld*	m_pWorld;
	btSequentialImpulseConstraintSolver* m_pSolver;
	btBroadphaseInterface*		m_pPairCache;
	btCollisionDispatcher*		m_pDispatcher;
	btDefaultCollisionConfiguration* m_pCollisionConfig;

	PhysicalObjectPtrList		m_Objects;
};

}
}

#endif

