#pragma once

#include <map>
#include "Mix/Graphics/IManager.h"

namespace Mix{

	class UserFile;
	class IWindow;

	namespace File{
		class IManager;
	}

	namespace Graphics{
		namespace Common{
			class Device;
		}

		namespace Utility{
			namespace Common{
				class TextPrinter;
			}
		}
	}
}

namespace Mix{ namespace Graphics{ namespace Common{

	class Manager : public Mix::Graphics::IManager
	{
	protected:
		static const wchar_t* FAILED_INITIALIZE;
		static const wchar_t* SUCCESS_INITIALIZE;
		static const wchar_t* FAILED_CREATETARGETTEXTURECHAIN;
		static const wchar_t* FAILED_CREATEFONT;
		static const wchar_t* FAILED_CREATELINEART;
		static const wchar_t* FAILED_CREATECANVAS;

	protected:
		//シェーダータイプ列挙定数
		enum SHADER_TYPES
		{
			SHADER_CANVAS_VS					= 0,	// VS : キャンバスレンダラー
			SHADER_CANVAS_COLOR_PS				= 1,	// PS : キャンバスレンダラー : テクスチャ無し
			SHADER_CANVAS_COLOR_AND_TEXTURE_PS	= 2,	// PS : キャンバスレンダラー : テクスチャ有り

			SHADER_LINE_VS						= 3,	// VS : ライン
			SHADER_LINE_PS						= 4,	// VS : ライン
		};

		//シェーダーバイナリ構造体
		struct SHADER_BINARY
		{
			enum VALUE{ NAME_SIZE = 64, };

			wchar_t name[SHADER_BINARY::NAME_SIZE];
			const void* pData;
			UInt32 dataSize;
		};

	public:
		//常駐エフェクトオプション列挙定数
		enum EFFECT_RESIDENT_OPT
		{
			ER_CANVAS				= 13,
			ER_LINE					= 14,
		};

		//バーテックスエフェクトシェーダー構造体
		enum VERTEX_EFFECT_SHADER
		{
			VES_DEFAULT			= 0,
			VES_MAX				= 1,
		};

		//ピクセルエフェクトシェーダー構造体
		enum PIXEL_EFFECT_SHADER
		{
			PES_DEFAULT					= 0,

			PES_CANVAS_COLOR			= 0,
			PES_CANVAS_COLOR_TEX		= 1,

			PES_MAX						= 2,
		};

		//バーテックスエフェクト構造体
		struct VERTEX_EFFECT
		{
			Mix::Graphics::IVertexLayout* pLayout;
			Mix::Graphics::IVertexShader* pShader[Manager::VES_MAX];

			VERTEX_EFFECT( void );
			void Dispose( void );
		};

		//ピクセルエフェクト構造体
		struct PIXEL_EFFECT
		{
			Mix::Graphics::IPixelShader* pShader[Manager::PES_MAX];

			PIXEL_EFFECT( void );
			void Dispose( void );
		};

	private:
		typedef std::map<UInt32, Manager::VERTEX_EFFECT> VertexEffectMap;
		typedef std::map<UInt32, Manager::PIXEL_EFFECT> PixelEffectMap;

	protected:
		Mix::IO::IManager* m_pFileMgr;

	private:
		Manager::VertexEffectMap m_ResidentVEMap;
		Manager::PixelEffectMap m_ResidentPEMap;

		Mix::Graphics::Utility::Common::TextPrinter* m_pTextPrinter;

	protected:
		Manager( void );
		virtual ~Manager( void );

		virtual Boolean OnInitialize(	const Mix::Point& targetSize,
										Mix::Graphics::SHADER_MODEL shaderModel, Boolean bFullscreen, Boolean bWaitVSync,
										Mix::UserFile* pSysReport ) = 0;

		virtual void OnDispose( void ) = 0;

		virtual void GetShaderBinary( Manager::SHADER_TYPES type, Manager::SHADER_BINARY& out ) = 0;

	public:
		Boolean Initialize( const Mix::Point& targetSize,
							Mix::Graphics::SHADER_MODEL shaderModel, Boolean bFullscreen, Boolean bWaitVSync,
							Int32 textTabSize, Int32 textTargetSize, Int32 initialTextTargetNum,
							Mix::UserFile* pSysReport );

		Boolean Update( void );

		void Dispose( void );

		void MessageProc( UInt32 msg, WPARAM wParam, LPARAM lParam );

		Manager::VERTEX_EFFECT* GetVertexEffectPtr( UInt32 opt = 0 );
		Manager::PIXEL_EFFECT* GetPixelEffectPtr( UInt32 opt = 0 );

		void GetTextPrinter( Mix::Graphics::Utility::Common::TextPrinter** ppTextPrinter );
		const Mix::Graphics::Utility::Common::TextPrinter* GetTextPrinterPtr( void ) const;

		virtual Mix::Graphics::Common::Device* GetDevicePtr( void ) = 0;

	public:
		virtual Boolean GetDevice( Mix::Graphics::IDevice** ppDevice );

		virtual Boolean CreateTargetTextureChain(	UInt32 width,
													UInt32 height,
													Mix::Graphics::FORMAT format,
													Mix::Graphics::Utility::ITargetTextureChain** ppTargetTextureChain,
													const wchar_t* pName );

		virtual Boolean CreateFontFromFile( const wchar_t* pFilePath, Mix::Graphics::Utility::IFont** ppFont );
		virtual Boolean CreateFontFromMemory( const wchar_t* pFilePath, Mix::Memory::IBuffer* pBuffer, Mix::Graphics::Utility::IFont** ppFont );

		virtual Boolean CreateCanvasRenderer( Mix::Graphics::Utility::ICanvasRenderer** ppCanvasRenderer, const wchar_t* pDebugName );
		virtual Boolean CreatePerspectiveRenderer( Mix::Graphics::Utility::IPerspectiveRenderer** ppPerspectiveRenderer, const wchar_t* pDebugName );
	};

}}}
