#ifndef BODY_H
#define BODY_H

namespace Salamander
{

class Shape;
struct Pick;

/*
** A body represents a solid object in the scene. We subclass Entity so that we have physical properties and can be
** added to a scene.
*/

class Body : public Entity
{
/*
** Collision performs the contact between two bodies, and therefore
** needs access to our private members.
*/
friend class World;
friend class Collision;
//friend class Joint;

public:
	Body();
	virtual ~Body();

	/*
	** Special processing based upon shape type is often branched at the body level. This
	** provides an easy access to the shape's ID.
	*/
	const UniqueId& shapeId();

	// setup methods

	void resetPhysics();

	virtual void setShape(Shape* shape);
	virtual Shape* getShape();

	void setFriction(double friction);
	double getFriction();

	void setMass(double mass);
	double getMass();

	// other methods
	World* world();

	virtual void updateMatrix();

	void applyTorque(double torque);
	void applyForce(Vec2 force);
	void applyLocalForce(Vec2 location, Vec2 force);
	void applyWorldForce(Vec2 location, Vec2 force);
	virtual void integrateForces(double ms);
	virtual void integrateVelocities(double ms);

	// overriding the shape methods to return the values from our resident shape methods
	virtual void applyMatrix(Mat2 matrix);
	virtual void clearMatrix();

	virtual double radius();
	virtual double radiusSquared();

	virtual bool isPointInside(Vec2 point);
	virtual Pick getRayIntersection(Vec2 location, Vec2 direction);

private :

	void updateLocalTransform();
	void updateMass();

protected:

	// members
	Vec2 velocity_;
	double angularVelocity_;

	Vec2 biasedVelocity_;
	double biasedAngularVelocity_;

	Vec2 force_;
	double torque_;

	double friction_;
	double mass_;
	double inverseMass_;
	double massMomentOfInertia_;
	double inverseMassMomentOfInertia_;

	Shape* shape_;

	// world structure
	World* world_;
};

}

#endif