#pragma once
#include "structures.h"
#include "Interfaces/textureinterface.h"
#include "Interfaces/meshinterface.h"
#include "Interfaces/materialinterface.h"
#include "matrix.h"
#include <string>
#include <stdint.h>


namespace M3D
{
class Mesh;
class Material;
class EngineInterface;
class OpenGLState;

/**
	@author Denis A. Biryukov <denis.birukov@gmail.com>
*/
class Model
{
	public:
		Model();
		~Model();
                /**
                 * Производит загрузку объекта из .m3d файла
                 * @param fname имя файла для загрузки
                 * @param engine указатель на интерфейс движка для которого грузится объект
                 */
                void load(const std::string &fname, EngineInterface *engine);
		/**
		 * Устанавливает материал объекта
		 * @param mat_id идиентификатор материала
		 * @param material указатель на материал
		 */
		void set_material( MaterialInterface mat_id, Material *material);
		/**
		 * Устанавливает меш объекта
		 * @param mesh_id идиентификатор меша
		 * @param mesh указатель на поверхность
		 */
		void set_mesh( MeshInterface mesh_id, Mesh *mesh );
		/**
		 * Устанавливает имя модели
		 * @param model_name имя модели
		 */
		void set_model_name( const std::string &model_name );

		/**
		 * Возвращает идиентификатор меша
		 * @return идиентификатор меша
		 */
		MeshInterface get_mesh() { return _mesh_id_;}

		/**
		 * Получение текущиш координат объекта
		 * @return текущие координаты объекта
		 */
		const Coords& get_location() const { return _location_; }
		/**
		 * Получение текущей ориентации объекта в пространстве 
		 * @return ориентация объекта в пространстве
		 */
		const Rotation& get_rotation() const { return _rotation_; }
		/**
		 * Получение текущего масшаба объекта
		 * @return текущий масштаб объекта
		 */
		const Scale& get_scale() const { return _scale_; }

		/**
		 * Смена текущего положения объекта 
		 * @param location новое положение объекта
		 */
		void set_location( const Coords &location );
		/**
		 * Смена текущей ориентации объекта в пространстве
		 * @param rotation новая ориентация объекта в пространстве
		 */
		void set_rotation( const Rotation &rotation );
		/**
		 * Смена масштаба объекта
		 * @param scale масштаб объекта
		 */
		void set_scale( const Scale &scale);
                
                /**
                 * Получение материала модели
                 * @return материал
                 */
                Material* get_material();
                /**
                 * Получение идиентификатора материала
                 * @return идиентификатор материала
                 */
                MaterialInterface get_material_interface() const;
                
                /**
                 * Установка признака рисования объекта
                 * @param is_drawable признак рисования
                 */
                void set_drawable( bool is_drawable );
                /**
                 * Проверка, требует ли объект своего отображения или нет
                 * @return true если объект требует отображения
                 */
                bool is_drawable( ) const;
                /**
                 * Производит вызов OpenGL команд для рисования объекта
                 * @param frame_num номер кадра
                 * @param gl_state указатель на состояние OpenGL контекста
                 */
                void draw(uint32_t frame_num, OpenGLState *gl_state);
    private:
		MeshInterface _mesh_id_;
		Mesh *_mesh_;
                
		std::string _source_file_;
		std::string _material_file_;
		std::string _mesh_file_;
		std::string _base_dir_;
		Coords _location_;
		Rotation _rotation_;
		Scale _scale_;
		
		std::string _model_name_;
                
                MaterialInterface _material_interface_;
                Material *_material_;
                
                bool _is_drawable_;
                uint32_t _last_frame_drawed_;

		GLMatrix4x4 _model_view_matrix_;
};

}
