#pragma once
#include <GL/glew.h>
#include <string>
#include <set>

namespace M3D
{
class Model;
class OpenGLState;
/**
 * Работа с поверхностями/
 * Работает всегда с одинаковыми форматами данных. см функцию load_data  
 * @author Denis A. Biryukov <denis.birukov@gmail.com>
 */
class Mesh
{
	public:
		Mesh();
		~Mesh();
		/**
		 * Производит инициализацию статических ограничений меша.
		 * @param vcm максимальное кол-во вертексов в меше
		 * @param icm максимальное кол-во индексов в меше
		 * @author Denis A. Biryukov
		 */
		static void set_limits( uint32_t vcm, uint32_t icm );

		/**
		 * Производит загрузку поверхности из .m3dme файла
		 * @param programID идиентификатор шейдерной программы
		 * @param base_dir базовый путь, по которому требуется искать файл
		 * @param source_file имя файла из которого загружается поверхность
		 * @author Denis A. Biryukov
		 */
		void load( int programID, const std::string &base_dir, const std::string &source_file );

		/**
		 * Получение максимального допустимого кол-ва вертексов в меше
		 * @return максимальное кол-во вертексов в меше 
		 * @author Denis A. Biryukov
		 */
		uint32_t get_vertex_count_max_() const { return _vertex_count_max_; }
		/**
		 * Получение максимального допустимого кол-ва индексов в меше
		 * @return максимальное кол-во индексов в меше 
		 * @author Denis A. Biryukov
		 */
		uint32_t get_index_count_max_() const {	return _index_count_max_; }
		/**
		 * Получение кол-ва вертексов в меше
		 * @return кол-во вертексов в меше 
		 * @author Denis A. Biryukov
		 */
		uint32_t get_vertex_count_() const{ return _vertex_count_; }
		/**
		 * Получение кол-ва индексов в меше
		 * @return кол-во индексов в меше 
		 * @author Denis A. Biryukov
		 */
		uint32_t get_index_count_() const{ return _index_count_; }

		/**
		 * Получение имени меша
		 * @return имя меша 
		 * @author Denis A. Biryukov
		 */
		std::string get_mesh_name() const{ return _mesh_name_; }
		/**
		 * Получение идиентификатора VAO (Vertex Array Object)
		 * @return идиентификатор VAO 
		 * @author Denis A. Biryukov
		 */
		GLuint get_vao_id() const { return _vao_id_; }
		/**
		 * Получение идиентификатора VBO (Vertex Buffer Object)
		 * @return идиентификатор VBO 
		 * @author Denis A. Biryukov
		 */
		GLuint get_vbo_id() const { return _vbo_id_; }
		/**
		 * Получение идиентификатора IBO (Index Buffer Object)
		 * @return идиентификатор IBO 
		 * @author Denis A. Biryukov
		 */
		GLuint get_ibo_id() const { return _ibo_id_; }
		/**
		 * Связывание меша с моделью
		 * @param obj объект с которым требуется связать меш 
		 * @author Denis A. Biryukov
		 */
		void link_model( Model *obj );
		/**
		 * Отвязывание меша от модели
		 * @param obj объект с которым требуется разорвать связь 
		 * @author Denis A. Biryukov
		 */
		void unlink_model( Model *obj );
                /**
                 * Производит вызов OpenGL команд для рисования объекта
                 * @param frame_num номер кадра
                 * @param gl_state указатель на состояние OpenGL контекста
                 */
                void draw(uint32_t frame_num, OpenGLState *gl_state);

	protected:
		uint32_t _vertex_count_;
		uint32_t _index_count_;
		std::string _mesh_name_;
		std::string _source_file_;
		uint8_t _primitive_type_;

		GLuint _vao_id_;
		GLuint _vbo_id_;
		GLuint _ibo_id_;
		GLuint _position_loc_;
		GLuint _normal_loc_;
		GLuint _texture_loc_;

		static uint32_t _vertex_count_max_;
		static uint32_t _index_count_max_;
		std::set<Model*> _associated_models_;
};

}

