#ifndef VIDEO_GL_MOGUL_H
#define VIDEO_GL_MOGUL_H
#include <string>
#include <map>
#include <vector>
#ifdef Revision
#undef Revision
#endif

#ifdef HAVE_CONFIG_H
#include <conf_config.h>
#endif

#ifdef WIN32
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#endif

#include <GL/glew.h>


#include "storage.h"
#include "video_int.h"

#ifdef Revision
#undef Revision
#endif
#define Revision "video_GL_mogul.h $Revision: 1.2 $"

/**
 * Хранение конфигурации. Допустимо использование нескольких файлов конфигурациию.
 * Для загрузки конфигурации используется интерфейс драйверов. Допустимо создание и использование одновременно нескольких хранилищ конфигурации с разными (или одинаковыми) драйверами.
 * Обеспечивается многопоточная безопасность.
 *@author Denis A. Birukov aka Messenger of death
 *@date 18.08.2005
 */

extern std::string storage_name;
extern std::string storage_prefix;

typedef int8_t Sint8;
typedef uint8_t Uint8;
typedef uint16_t Uint16;
typedef int16_t Sint16;
typedef uint32_t Uint32;
typedef int32_t Sint32;

class OpenGL_Video_Features: public Video_Features
{
	public:
		virtual bool _support_blit_abs() { return false;}
		virtual bool _support_blit() { return false;}
		virtual bool _support_create_surface_abs() { return true;}
		virtual bool _support_create_surface() { return true;}
		virtual bool _support_create_surface_from_surface() { return false;}
		virtual bool _support_get_main_surface() { return false;}
		virtual ~OpenGL_Video_Features() {}}
;

class OpenGL_Surface;

class OpenGL_Video: public Video_Interface
{
	public:
		virtual const Video_Features& _get_features();
		virtual std::string _get_driver_name();
		virtual bool _free_surface ( std::string name ,std::string grp="" );
		virtual bool _blit ( std::string from, int from_x, int from_y, std::string to, int to_x, int to_y , std::string from_grp = "", std::string to_grp = "" ) { return false;}
		virtual bool _blit ( std::string from, double from_x, double from_y, std::string to, double to_x, double to_y, std::string from_grp = "", std::string to_grp = "" ) { return false;}
		virtual bool _add_sprite(std::string surf, std::string group = "" );
		virtual bool _add_sprite(Video_Sprite *spr );
		virtual bool _add_particles ( std::string name, std::string group="" );
		virtual bool _create_surface ( int xs, int ys, std::string name, std::string group_name = "", bool rewrite = true );
		virtual bool _create_surface ( double xs, double ys, std::string name, std::string group_name = "", bool rewrite = true );
		virtual bool _set_current_group ( std::string name );
		virtual std::string _get_current_group();
		virtual std::string _get_main_surface() { return "";}
		virtual Video_Surface* _get_surface ( std::string name, std::string group_name="" );
		virtual Video_Sprite* _get_sprite ( std::string sprite_name, std::string group_name="" );
		virtual Video_Particles* _get_particles ( std::string name, std::string group_name="" );
		virtual bool _create_surface ( Video_Surface *surf, std::string name, std::string group_name = "", bool rewrite = true );
		virtual void _draw();
		virtual bool _init();
		virtual bool _deinit();
		virtual void show_mouse ( bool state=true );
		virtual std::string _get_error() { return _error;}
		virtual void _get_mouse_position ( int *x, int *y );
		virtual void _get_mouse_position ( double *x, double *y );
		virtual EVENT_TYPE _get_event();
		virtual bool _create_sprite ( std::string name, std::string group_name, std::string surf_name, std::string surf_group, bool rewrite = true );
		virtual bool _create_particles ( std::string name, std::string group_name, std::string surf_name, std::string surf_group, int count, bool rewrite=false );

		virtual bool check_surface_point ( double x_pos, double y_pos, double x_point, double y_point, std::string surface_name, std::string group_name );
		virtual Sint16 _get_width(){return _w_;}
		virtual Sint16 _get_height(){return _h_;}
		
		
		OpenGL_Video() ;
		virtual ~OpenGL_Video();
			
	private:
		struct GL_State
		{
			bool gl_blend;
		} _GL_State;
		
		void _draw_sprites();
		void _draw_particles();
		Sint16 _w_;
		Sint16 _h_;
		Sint16 _base_h_;
		float _base_scale_;
		Uint8 _bpp_;
		bool _DoubleBuffer_;
		bool _FullScreen_;
		bool _mouse_;
		std::string _cur_group_;
		std::string _error;
		std::string _caption_;
		int _max_point_size_;
		int _max_element_vertices_;
		int _max_element_indeces_;
		/*			std::string storage_name;
					std::string storage_prefix;*/

		Storage<std::string, Storage<std::string, Video_Surface*>* > _surfaces_;
		Storage<std::string, Storage<std::string, Video_Sprite*>* > _sprites_;
		Storage<std::string, Storage<std::string, Video_Particles*>* > _particles_;
		std::vector<Video_Sprite*> _sprites_draw_list_; 
		std::vector<Video_Particles*> _particles_draw_list_;
};

class OpenGL_Surface : public Video_Surface
{
	public:
		OpenGL_Surface ( );
		~OpenGL_Surface();

		virtual void _update_ ( );

		GLuint _tex_id_;
};
class OpenGL_Particles : public Video_Particles
{
	public:
		OpenGL_Particles():Video_Particles(), _particles_(0), _colors_(0), _have_texture_(false), _p_buf_id_(0), _c_buf_id_(0){};
		/** Установка координаты отдельной частицы*/
		bool _set_particle ( int particle_num, float x, float y, int r=255, int g=255, int b=255, float a=1.0 );
		/** получает параметры отдельной частицы*/
		bool _get_particle ( int particle_num, float *x, float *y, int *r=0, int *g=0, int *b=0, float *a=0 );
		~OpenGL_Particles();
	private:
		//Описывают поверхность, могут отсутствовать.
		std::string _surface_name_;
		std::string _surface_group_;
		GLfloat *_particles_;
		GLfloat *_colors_;
		bool _have_texture_;
		GLuint _p_buf_id_;
		GLuint _c_buf_id_;
		friend class OpenGL_Video;

};

extern "C" Video_Interface* _get_video_driver ( std::string * params, int params_num );


#endif
