/** \file Skeleton.h
 * \brief The header file for the 'Skeleton' class.
 */

#pragma once
// OSkA Includes
#include "OSkA.h"
#include "Bone.h"
#include "Animation.h"
// Other Includes
#include <vector>

namespace OSkA
{
	/** \brief A Skeleton stores a list of Bones and a list of Animations.
	 *
	 * The Skeleton class is used as a simple storage for the bones
	 * and the animations of our skeleton.
	 *
	 * The Skeleton can be automatically loaded from an .skeleton.xml
	 * file. Furthermore the Skeleton class offers simple methods
	 * for manual adding Bones and Animations.
	 *
	 * The Bones are stored in a list by their id(used as an index), and
	 * can be accessed by the id or by the Bone's name.
	 *
	 * The Animations are stored in a list, and can easily be accessed by their
	 * names. But we also provide a method to access the animations by index.
	 *
	 * For performance reasons the Skeleton class is not directly used
	 * by the Shader. Instead we use the AnimationCooker, which performs
	 * a lot of preprocessing and so leads us to better performance.
	 */
	class Skeleton
	{
	public:
		/** \brief Default Constructor.
		 */
		Skeleton();
		/** \brief Constructor.
		 *
		 * Initializes the Skeleton by loading the data from a file.
		 * \param filename	The .skeleton.xml file which will be loaded.
		 */
		Skeleton(char* filename);
		/** \brief Destructor.
		 */
		~Skeleton();

		void clear();
		void clearTempData();

		/** \brief Loads a Skeleton from a file.
		 *
		 * Loads a Skeleton from a .skeleton.xml file.
		 * \param filename	The .skeleton.xml file which will be loaded.
		 * \return	true - loading succesfull, false loading not successfull
		 */
		bool loadFile(char* filename);

		/** \brief Adds a new Bone to the Skeleton.
		 *
		 * A new Bone is added to the skeleton. The Bone can later be accessed by the id.
		 * \param id		The id of the Bone.
		 * \param name		The name of the Bone.
		 * \param transform	The bind pose of the Bone.
		 */
		void addBone(int id, char* name, Matrix* transform);
		/** \brief Sets the bone parents id.
		 *
		 * The parent of Bone 'name' is set as Bone 'parent'.
		 * \param name	Name of the Bone whose parent will be set.
		 * \param parent	Name of the Parent Bone.
		 */
		void setBoneParent(char* name, char* parent);
		/** \brief Returns the id of a Bone.
		 *
		 * Returns the id of the Bone with the given name.
		 * \param name	The name of the Bone.
		 * \return The id of the Bone.
		 */
		int getBoneId(char* name);
		/** \brief Returns the Bone with the given id.
		 *
		 * The pointer refers to an intern Bone object of this class. So by changing
		 * the object you will affect this class. You don't have to delete it, this class
		 * itself will take care of it.
		 * \param id	The id of the Bone.
		 * \return Pointer to the Bone.
		 */
		Bone* getBone(int id);
		/** \brief Returns the Bone with the given name.
		 *
		 * The pointer refers to an intern Bone object of this class. So by changing
		 * the object you will affect this class. You don't have to delete it, this class
		 * itself will take care of it.
		 * \param name	The name of the Bone.
		 * \return Pointer to the Bone.
		 */
		Bone* getBone(char* name);
		/** \brief Returns the number of Bones.
		 *
		 * Returns the number of Bones stored in this Skeleton.
		 * \return Number of Bones.
		 */
		int getBonesCount();

		/** \brief Adds a new Animation to the Skeleton
		 *
		 * A new Animation with a given name and length is added. The Animation can later be accessed by the name.
		 * \param name	The name of the Animation.
		 * \param length	The length of the Animation.
		 */
		void addAnimation(char* name, float length);
		/** \brief Returns the Animation with a given name.
		 *
		 * The pointer refers to an intern Animation object of this class. So by changing
		 * the object you will affect this class. You don't have to delete it, this class
		 * itself will take care of it.
		 * \param name	The name of the Animation.
		 * \return Pointer to the Animation.
		 */
		Animation* getAnimation(char* name);
		/** \brief Returns the Animation with a given id.
		 *
		 * The pointer refers to an intern Animation object of this class. So by changing
		 * the object you will affect this class. You don't have to delete it, this class
		 * itself will take care of it.
		 * \param index	The id of the Animation.
		 * \return Pointer to the Animation.
		 */
		Animation* getAnimation(int id);
		/** \brief Returns the id of the Animation with given name.
		 *
		 * \param name	The name of the Animation.
		 * \return Id of the Animation.
		 */
		int getAnimationId(char* name);
		/** \brief Returns the number of Animations in the Skeleton.
		 *
		 * \return Number of Animations.
		 */
		int getAnimationsCount();

		/** \brief Returns the full animation transform for a Bone at a given time.
		 *
		 * The full animation transform(based on the hierarchy of the bones)is
		 * calculated for the given animation, bone and time.
		 * Yourself will have to delete the Matrix object refered by the returned pointer.
		 * \param animation	The id of the Animation the transform will be calculated for.
		 * \param bone		The id of the Bone the transform will be calculated for.
		 * \param time		The time the transform will be calculated for.
		 * \return The full animation transform.
		 */
		Matrix* getFullAnimTransform(int animation, int bone, float time);
		/** \brief Returns the full bone transform.
		 *
		 * The full bone transform(based on the hierarchy of the bones)is calculated and returned.
		 * Yourself will have to delete the Matrix object refered by the returned pointer.
		 * \param bone		The id of the Bone the transform will be calculated for.
		 * \return The full bone transform.
		 */
		Matrix* getFullBoneTransform(int bone);
	private:
		/** \brief The list of Bones.
		 */
		std::vector<Bone*> bones;

		std::vector<Matrix*> tempBoneTransforms;

		/** \brief The list of Animations.
		 */
		std::vector<Animation*> animations;
	};
}

