#ifndef ENTITY_H
#define ENTITY_H

#include "Node.h"

namespace Salamander
{

/*
** An Entity is a scene graph node with functionality allowing the user to translate and rotate it. 
** These transformations can be done with a local frame of reference, or a world frame of reference. 
*/
class Entity : public Node
{
friend class Sprite;

public:
	/*
	** All transformations are carried out in the local space or in the world space. Use 'setReferenceFrame()'
	** to set how this entity sees the world.
	*/
	enum ReferenceFrame
	{
		LOCAL,
		WORLD
	};

public:
	/*
	** Destructor. Entities are a type of Node, and therefore can be deleted directly and will remove themselves
	** cleanly from the scene graph.
	*/
	virtual ~Entity();

	/*
	** The reference frame is used to change the way co-ordinates are used within the entity. When LOCAL, the get/set
	** methods return values in relation to the parent object, or if no parent exists, then in relation to the world.
	** When the reference frame is WORLD, then the get/set methods will return values in relation to the world, irrespective
	** of parent transforms.
	*/
	void setReferenceFrame(ReferenceFrame referenceFrame);
	ReferenceFrame getReferenceFrame();

	/*
	** Set/Get the translation and rotation as a matrix transform, in relation 
	** to the reference frame.
	*/
	void setTransform(const Mat2& transform);
	Mat2& getTransform();

	/*
	** Set/Get the translation, in relation to the reference frame.
	*/
	void setTranslation(const Vec2& translation);
	Vec2 getTranslation() const;

	/*
	** Set/Get the scale, independant of reference frame.
	*/
	void setScale(const Vec2& scale);
	Vec2 getScale() const;

	/*
	** Set/Get the rotation in radians, in relation to the reference frame.
	*/
	void setRotation(double rotation);
	double getRotation();

	/*
	** We override the return type of 'getChild()' so that any calls return the child as an entity and not a node. This
	** is safe in this instance because the child of an entity is never a superclass of entity.
	*/
	virtual Entity* getChild(unsigned int index);

protected:
	/*
	** This is an abstract class and cannot be instantiated.
	*/
	Entity();

	/*
	** Update child transforms, including the final attachment -
	** such as geometry, lighting, etc.
	*/
	virtual void propogate();

private:

	/*
	** Members to store information relating to the world and local transforms. Both are
	** cached for fast repeat access.
	*/
	ReferenceFrame referenceFrame_;
	Mat2 local_;
	Mat2 world_;
};

}

#endif // ENTITY_H