#ifndef WORLD_H
#define WORLD_H

namespace Salamander
{

/*
** Maintains physical bodies in the world, and is the interface from the game to the simulation.
*/

class Joint;
class Collision;
class CollisionKey;
class Contact;
class Body;
class Composite;

struct Pick
{
	Pick()
	{
		body = NULL;
		distance = 0.0f;
	}
	Body* body;
	double distance;
};

class World
{
friend class Application;

public:
	World(unsigned int iterations = 10);
	~World();

	void timeStep(double ms);

	void addBody(Body* body);
	Body* getBody(unsigned int i);
	bool removeBody(Body* body);
	unsigned int getNumBodies();

	void addJoint(Joint* joint);
	Joint* getJoint(unsigned int i);
	bool removeJoint(Joint* joint);
	unsigned int getNumJoints();

	Pick pickBody(Vec2 location, Vec2 direction = Vec2());
	Body* pickUpBody(Vec2 location);

	void updateBodyMatrices();

private:

	void findCollisions();
	void updateBodyForces(double ms);
	void performPrecomputations(double inv_ms);
	void performIterations();
	void performPostcomputations();
	void updateBodyVelocities(double ms);

	unsigned int iterations_;
	std::vector<Body*> bodies_;
	std::vector<Joint*> joints_;
	std::map<CollisionKey, Collision> collisions_;

	typedef std::vector<Body*>::iterator BodyIterator;
	typedef std::vector<Joint*>::iterator JointIterator;
	typedef std::map<CollisionKey, Collision>::iterator CollisionIterator;

	typedef std::pair<CollisionKey, Collision> CollisionPair;

public:

	static Vec2 gravity_;
};

}

#endif
