#ifndef __OPENGLDEVICEC_H__
#define __OPENGLDEVICEC_H__

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl\gl.h>

// forward declaration

namespace PajaSystem {
	class OpenGLDeviceC;
};

#include "PajaTypes.h"
#include "BBox2C.h"
#include "ColorC.h"
#include "Vector2C.h"
#include "DeviceInterfaceI.h"
#include "GraphicsDeviceI.h"
#include "OpenGLViewportC.h"
#include "OpenGLGUIDrawInterfaceC.h"
#include "DeviceFeedbackC.h"
#include "OpenGLBufferC.h"


namespace PajaSystem {

//////////////////////////////////////////////////////////////////////////
//
//  OpenGL Device Driver Class ID
//

	const PluginClass::ClassIdC	CLASS_OPENGL_DEVICEDRIVER = PluginClass::ClassIdC( 0, 10000 );


	class OpenGLDeviceC : public GraphicsDeviceI
	{
	public:
		static OpenGLDeviceC*			create_new();
		virtual Edit::DataBlockI*		create();
		virtual PluginClass::ClassIdC	get_class_id() const;
		virtual const char*				get_class_name();
		virtual DeviceInterfaceI*		query_interface( const PluginClass::SuperClassIdC& rSuperClassId );
		virtual PajaTypes::uint32		save( FileIO::SaveC* pSave );
		virtual PajaTypes::uint32		load( FileIO::LoadC* pLoad );

		virtual bool					init( HINSTANCE hInstance, HWND hParent, PajaTypes::int32 i32ID, PajaTypes::uint32 ui32Flags,
											PajaTypes::uint32 ui32Width = 0, PajaTypes::uint32 ui32Height = 0, PajaTypes::uint32 ui32BPP = 0,
											PajaSystem::DeviceFeedbackC* pFeedback = 0 );
		virtual void					destroy();
		virtual void					flush();
		virtual void					activate();
		virtual HWND					get_hwnd();
		virtual bool					configure();

		virtual bool					set_fullscreen( PajaTypes::uint32 ui32Width, PajaTypes::uint32 ui32Height,
														PajaTypes::uint32 ui32BPP = 0 );
		virtual bool					set_windowed();

		virtual void					set_size( PajaTypes::int32 int32X, PajaTypes::int32 int32Y,
														PajaTypes::int32 i32Width, PajaTypes::int32 i32Height );

		// clear device
		virtual void					clear_device( PajaTypes::uint32 ui32Flags, const PajaTypes::ColorC& rColor = PajaTypes::ColorC(),
														PajaTypes::float32 f32Depth = 1.0f, PajaTypes::int32 i32Stencil = 0 );

		virtual bool					begin_draw();
		virtual void					end_draw();

		// Pushes current state and prepares to draw effects
		virtual void					begin_effects();
		virtual void					end_effects();

		//! Returns new graphics buffer.
		virtual GraphicsBufferI*				create_graphicsbuffer();

		//! Sets the recommended size of the temp buffers.
		virtual void										set_temp_graphicsbuffer_size( PajaTypes::uint32 ui32Width, PajaTypes::uint32 ui32Height );
		//! Returns temporary graphics buffer.
		virtual GraphicsBufferI*				get_temp_graphicsbuffer( PajaTypes::uint32 ui32Flags );
		//! Frees temporary graphics buffer.
		virtual void										free_temp_graphicsbuffer( GraphicsBufferI* pGBuf );

		//! Sets rendering target.
		virtual GraphicsBufferI*				set_render_target( GraphicsBufferI* pBuffer );
		virtual GraphicsBufferI*		get_render_target();

		virtual HDC						get_hdc();
		virtual HGLRC					get_glrc();

	private:

		OpenGLDeviceC();
		virtual ~OpenGLDeviceC();


		void					choose_resolution( PajaTypes::uint32& ui32Width, PajaTypes::uint32& ui32Height );

		static bool				set_pixelformat( HDC hDC );

		static LRESULT CALLBACK	stub_window_proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

		HWND					m_hWnd;
		HDC						m_hDC;
		HGLRC					m_hGLRC;

		LONG					m_lSavedWindowStyle;
		LONG					m_lSavedExWindowStyle;
		PajaTypes::uint32		m_ui32SavedCreateFlags;
		HWND					m_hSavedParent;
		RECT					m_rSavedWindowRect;
		PajaTypes::BBox2C		m_rSavedViewport;

		PajaTypes::uint32		m_ui32CreateFlags;

		bool					m_bResolutionChanged;

		OpenGLViewportC*			m_pInterface;
		OpenGLGUIDrawInterfaceC*	m_pGUIDrawInterface;
		DeviceFeedbackC*			m_pFeedback;
		OpenGLBufferC*				m_pCurrentBuffer;

		OpenGLBufferC*				m_pTempGBuffer;

		static HGLRC			m_hMainGLRC;
		static PajaTypes::int32	m_i32RefCount;
		static bool				m_bClassCreated;
		static PajaTypes::int32	m_i32InstCount;
	};

};

#endif // __OPENGLDEVICEC_H__