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

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

namespace OSkA
{
	/** \brief A Mesh contains geometric and animation data of a Mesh.
	 *
	 * The Mesh class contains storages for geometric data(vertices, normals, indices)
	 * and also for animation data(bone/vertex weights).
	 *
	 * The Mesh offers simple methods for add vertices, normals, etc manually, or to
	 * load them from a file.
	 *
	 * For performance reasons the Mesh class is not directly used by the Shader and for
	 * rendering. Instead the BoneCooker class will be used for the shader, and it is
	 * advised just to use the Mesh as a temporal storage for preparing the geometric data.
	 */
	class Mesh
	{
	public:
		/** \brief Default Constructor
		 */
		Mesh();
		/** \brief Destructor
		 */
		~Mesh();

		/** \brief Loads the Mesh data from a file.
		 *
		 * This method loads the Mesh data from a .mesh.xml file.
		 * It does not support the full .mesh.xml format. It is limited to:
		 * shared geometry, triangle_lists, vertices/normals/indices/bone weights.
		 * For examples see the tutorial programs, they all contain .mesh.xml
		 * files where you can see what is supported.
		 * \param filename	The .mesh.xml file that will be loaded.
		 * \return	true - loading succesfull, false loading not successfull
		 */
		bool loadFile(char* filename);

		/** \brief Adds a new vertex.
		 *
		 * \param x	Vertex x coordinate.
		 * \param y	Vertex y coordinate.
		 * \param z	Vertex z coordinate.
		 */
		void addVertex(float x, float y, float z);
		/** \brief Adds a new normal.
		 *
		 * \param x	Normals x coordinate.
		 * \param y	Normals y coordinate.
		 * \param z	Normals z coordinate.
		 */
		void addNormal(float x, float y, float z);
		/** \brief Adds a new triangle
		 *
		 * \param v1	Index of vertex 1.
		 * \param v2	Index of vertex 2.
		 * \param v3	Index of vertex 3.
		 */
		void addTriangle(int v1, int v2, int v3);
		/** \brief Adds a new Bone weight.
		 *
		 * A new Bone weight for the given bone and vertex is set.
		 * An existing bone weight for this bone/vertex will be
		 * overwritten
		 * \param vertex	The vertex index.
		 * \param bone		The bone id.
		 * \param weight	The bone weight.
		 */
		void addBoneAssignement(int vertex, int bone, float weight);

		/** \brief Returns the vertex array.
		 *
		 * Returns a pointer to the vertex array of the stored vertices.
		 * For performance reasons, it's advised not to use this method
		 * for rendering.
		 * The Mesh won't delete the array, so yourself have to delete
		 * the array.
		 * \return The vertex array
		 */
		float* getVertexArray();
		/** \brief Returns the normal array.
		 *
		 * Returns the normal array of the stored normals. For performance
		 * reasons, it's advised not to use this method for rendering.
		 * The Mesh won't delete the array, so yourself have to delete
		 * the array.
		 * \return The normal array
		 */
		float* getNormalArray();
		/** \brief Returns the index array.
		 *
		 * Returns the index array of the stored triangles. For performance
		 * reasons, it's advised not to use this method for rendering.
		 * The Mesh won't delete the array, so yourself have to delete
		 * the array.
		 * \return The index array
		 */
		int* getTriangleArray();
		/** \brief Returns the bone weights for the given vertex.
		 *
		 * Returns the VertexBones storage(containing bone weights)of the given vertex.
		 * You don't have to delete the object the pointer belongs to, the Mesh
		 * itself will delete it.
		 * \param vertex_index	The index of the vertex.
		 * \return The VertexBones storage of the given vertex.
		 */
		VertexBones* getVertexBones(int vertex_index);

		/** \brief Returns the number of stored vertices.
		 *
		 * Returns the number of stored vertices(this is of couse the same
		 * as the number of stored normals, cause we have for each vertex a
		 * normal stored)
		 * \return Number of Vertices.
		 */
		int getVerticesCount();
		/** \brief Returns the number of stored triangles.
		 *
		 * \return Number of triangles
		 */
		int getTrianglesCount();
	private:
		/** \brief Deletes all stored vertices, normals, etc.
		 */
		void clear();

		/** \brief A list of vertices.
		 */
		std::vector<float> vertices;
		/** \brief A list of normals.
		 */
		std::vector<float> normals;
		/** \brief A list of indices.
		 *
		 * The indices refer to the vertices/normals. 3 of the indices form a triangle.
		 */
		std::vector<int> triangleIndices;
		/** \brief A list of bone weights.
		 *
		 * The vertex id of the particular bone weights is used as an index. So by
		 * knowing a vertex we can directly access its bone weights.
		 */
		std::vector<VertexBones*> boneWeights;
	};
}