#ifndef NODE_H
#define NODE_H

namespace Salamander
{

/*
** A Node is an abstract base class used by the scere graph. It has the ability to form a hierarchy
** of parents and children, but contains no positional data. This class is used internally and 
** should not be used by client applications.
*/
class Node
{
	/*
	** Node can only be subclassed by Entity to form a screen graph, and by SceneManager as the root.
	*/
	friend class Entity;
	friend class SceneManager;
	
public:
	/*
	** Destructor. This will clean up the memory for any children of this node, as well as removing
	** ourselves cleanly from the parent node.
	*/
	virtual ~Node();

	/* 
	** Frame is called once per object each game cycle and should be used to run updates within objects.
	*/
	virtual void frame();

	/*
	** Assemble is called prior to a render, and allows the node to update its geometry ready to be
	** rendered. Geometries must first be registered with the renderer otherwise they will not show. This
	** function must be implemented by subclasses.
	*/
	virtual void assemble();

	/*
	** Any class derived from Node can be added to the scene graph. Returns false if the child 
	** already exists.
	*/
	virtual bool addChild(Node& child);

	/*
	** Called when this node has been added to the scene graph
	*/
	virtual bool onAdded(Node& parent);

	/*
	** Returns the child at the given position in the array. If there are no children or the index is
	** out of bounds, then NULL is returned.
	*/
	virtual Node* getChild(unsigned int index) const;

	/*
	** Returns the number of children that this node has.
	*/
	virtual unsigned int getChildCount() const;

	/*
	** Returns true if there is a child at the given index and it was successfully removed. Returns false
	** if the index is out of bounds or the child could not be removed.
	*/
	virtual bool removeChild(unsigned int index);

	/*
	** Returns true if the child exists. Returns false if the child does not exist or if it could not be
	** removed.
	*/
	virtual bool removeChild(Node& child);
	
	/*
	** Called when this node has been removed from the scene graph
	*/
	virtual bool onRemoved(Node& parent);

	/*
	** Returns the parent of this node. If the node is not attached to the scene graph or is the root
	** node, then NULL will be returned.
	*/
	Node* getParent() const;

private:
	/*
	** This is a private abstract base class and cannot be instantiated nor directly subclassed by client
	** applications.
	*/
	Node();

	/*
	** This stores a list of child nodes. Subclasses of Node should use getChild() to access children.
	*/
	std::vector<Node*> children_;

	/*
	** This is our parent, and will be NULL for the root node, and any node not yet attached to the scene graph.
	** Subclasses of Node should use getParent() to access this member.
	*/
	Node* parent_;

};

}

#endif // NODE_H
