#pragma once

#include "Mix/Scene/ISkyDome.h"
#include "Mix/Private/Scene/Common/RendererObject.h"

namespace Mix{ namespace Scene{ namespace Common{

	class AtmosphereScatter;

	class SkyDome : public Mix::Scene::ISkyDome, public Mix::Scene::Common::RendererObject
	{
	private:
		struct VERTEX
		{
			Float32 pos[4];
			Float32 tex[2];
		};

	public:
		enum INTERNAL_CONSTANT
		{
			QL_MAX	= 3,	// 品質の最大数

			CL_0	= 0,	// 雲レイヤー0
			CL_1	= 1,	// 雲レイヤー1
			CL_MAX	= 2,	// 雲レイヤーの最大数
		};

		struct DRAW_SUBSET
		{
			UInt32 vertexStart;
			UInt32 vertexNum;
			UInt32 indexStart;
			UInt32 indexNum;
		};

		struct INTERNAL_CLOUD_LAYER_SETTINGS
		{
			Mix::Vector2 texOffset;
		};

		struct INTERNAL_CLOUD_GLOBAL_SETTINGS
		{
			Float32 asCornerMul;
			Float32 asDarkness;
		};

	public:
		static SkyDome* CreateInstance( Float32 radius, Float32 height );

	private:
		Mix::Scene::Common::AtmosphereScatter* m_pAS;

		Boolean m_bEnabled;

		Mix::Scene::ISkyDome::CONSTRAINT_TYPE m_CRType;

		ISkyDome::QUALITY m_HemisphereQuality;
		Mix::Scene::ISkyDome::HEMISPHERE_SETTINGS m_HemisphereSettings;

		ISkyDome::PLANET_INFO m_PlanetInfo;

		ISkyDome::BASE_SETTINGS m_BaseSettings;
		Mix::Graphics::ITexture* m_pBaseTex;

		Mix::Scene::ISkyDome::SUN_LIGHT m_SunLight;
		Mix::Vector3 m_SunPos;

		Boolean m_bCloudEnabled;
		UInt32 m_CloudLayerNum;
		Mix::Graphics::ITexture* m_pCloudTexs[Mix::Scene::Common::SkyDome::CL_MAX];
		ISkyDome::CLOUD_LAYER_SETTINGS m_CloudLayerSettings[Mix::Scene::Common::SkyDome::CL_MAX];
		SkyDome::INTERNAL_CLOUD_LAYER_SETTINGS m_InternalCloudLayerSettings[Mix::Scene::Common::SkyDome::CL_MAX];
		ISkyDome::CLOUD_GLOBAL_SETTINGS m_CloudGlobalSettings;
		SkyDome::INTERNAL_CLOUD_GLOBAL_SETTINGS m_InternalCloudGlobalSettings;

		Boolean m_bExistsPanorama;
		ISkyDome::QUALITY m_PanoramaQuality;
		Boolean m_bPanoramaEnabled;
		ISkyDome::PANORAMA_SETTINGS m_PanoramaSettings;
		Mix::Graphics::ITexture* m_pPanoramaTex;

		Mix::Graphics::IVertexBuffer* m_pVertexBuffer;
		Mix::Graphics::IIndexBuffer* m_pIndexBuffer;

		SkyDome::DRAW_SUBSET m_DomeSubset;
		SkyDome::DRAW_SUBSET m_PanoramaSubset;

	private:
		SkyDome( Float32 radius, Float32 height );
		virtual ~SkyDome( void );

		static void RotateTexOffset( Mix::Vector2& value );

	public:
		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::Common::SkyDome
		////////////////////////////////////////////////////////////////////////////////////////////////////

		Boolean Initialize( Mix::Graphics::IDevice* pDevice, UInt32 heQuality, UInt32 paQuality, const wchar_t* pDebugName );

		void Attach( Mix::Scene::Common::AtmosphereScatter* pAS );
		void Detach( void );

		void Update( Float32 dt );

		Mix::Graphics::ITexture* GetBaseTexturePtr( void );

		Boolean IsCloudAvailabled( void ) const;
		Boolean IsPanoramaAvailabled( void ) const;

		UInt32 GetValidCloudLayerNum( void ) const;
		const ISkyDome::CLOUD_LAYER_SETTINGS* GetCloudLayerSettings( void ) const;
		const SkyDome::INTERNAL_CLOUD_LAYER_SETTINGS* GetInternalCloudLayerSettings( void ) const;
		const SkyDome::INTERNAL_CLOUD_GLOBAL_SETTINGS& GetInternalCloudGlobalSettings( void ) const;
		Mix::Vector4 ComputeCloudColorAS( void ) const;

		Mix::Graphics::ITexture* GetCloudTexturePtr1( void );
		Mix::Graphics::ITexture* GetCloudTexturePtr2( void );
		Mix::Graphics::ITexture* GetPanoramaTexturePtr( void );

		Mix::Graphics::IVertexBuffer* GetVertexBufferPtr( void ) const;
		Mix::Graphics::IIndexBuffer* GetIndexBufferPtr( void ) const;

		const SkyDome::DRAW_SUBSET* GetDomeSubsetPtr( void ) const;
		const SkyDome::DRAW_SUBSET* GetPanoramaSubsetPtr( void ) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::ISkyDome
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Boolean IsEnabled( void ) const;
		virtual void SetEnabled( Boolean state ); 

		virtual Mix::Scene::ISkyDome::CONSTRAINT_TYPE GetConstraintType( void ) const;
		virtual void SetConstraintType( Mix::Scene::ISkyDome::CONSTRAINT_TYPE type );

		virtual Mix::Scene::ISkyDome::QUALITY GetHemisphereQuality( void ) const;
		virtual const Mix::Scene::ISkyDome::HEMISPHERE_SETTINGS& GetHemisphereSettings( void ) const;
		virtual void SetHemisphereSettings( const Mix::Scene::ISkyDome::HEMISPHERE_SETTINGS& settings );

		virtual const Mix::Scene::ISkyDome::PLANET_INFO& GetPlanetInfo( void ) const;

		virtual const Mix::Scene::ISkyDome::BASE_SETTINGS& GetBaseSettings( void ) const;
		virtual void SetBaseSettings( const Mix::Scene::ISkyDome::BASE_SETTINGS& settings );
		virtual Boolean GetBaseTexture( Mix::Graphics::ITexture** ppTexture );
		virtual void SetBaseTexture( Mix::Graphics::ITexture* pTexture );

		virtual const Mix::Scene::ISkyDome::SUN_LIGHT& GetSunLight( void ) const;
		virtual const Mix::Vector3& GetSunPosition( void ) const;
		virtual void SetSunPosition( const Mix::Vector3& pos );

		virtual Boolean IsCloudEnabled( void ) const;
		virtual void SetCloudEnabled( Boolean state );
		virtual UInt32 GetCloudLayerNum( void ) const;
		virtual Boolean GetCloudLayerTexture( UInt32 layerIndex, Mix::Graphics::ITexture** ppTex );
		virtual Boolean SetCloudLayerTexture( UInt32 layerIndex, Mix::Graphics::ITexture* pTex );
		virtual const Mix::Scene::ISkyDome::CLOUD_LAYER_SETTINGS& GetCloudLayerSettings( UInt32 layerIndex ) const;
		virtual UInt32 SetCloudLayerSettings( const Mix::Scene::ISkyDome::CLOUD_LAYER_SETTINGS* settings, UInt32 num );
		virtual UInt32 LockCloudLayerSettings( Mix::Scene::ISkyDome::CLOUD_LAYER_SETTINGS** settings, UInt32 num );
		virtual const Mix::Scene::ISkyDome::CLOUD_GLOBAL_SETTINGS& GetCloudGlobalSettings( void ) const;
		virtual void SetCloudGlobalSettings( const Mix::Scene::ISkyDome::CLOUD_GLOBAL_SETTINGS& settings );
		virtual void ResetCloud( void );

		virtual Boolean ExistsPanorama( void ) const;
		virtual Mix::Scene::ISkyDome::QUALITY GetPanoramaQuality( void ) const;
		virtual Boolean IsPanoramaEnabled( void ) const;
		virtual void SetPanoramaEnabled( Boolean state );
		virtual const Mix::Scene::ISkyDome::PANORAMA_SETTINGS& GetPanoramaSettings( void ) const;
		virtual void SetPanoramaSettings( const Mix::Scene::ISkyDome::PANORAMA_SETTINGS& param );
		virtual Boolean GetPanoramaTexture( Mix::Graphics::ITexture** ppTex );
		virtual void SetPanoramaTexture( Mix::Graphics::ITexture* pTex );
		virtual Mix::Vector2 GetPanoramaTextureAspectRatio( void ) const;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		// Mix::Scene::IRendererObject
		////////////////////////////////////////////////////////////////////////////////////////////////////

		virtual Mix::Scene::IRendererObject::TYPE GetType( void ) const;
		virtual Boolean IsRendering( void ) const;

	public:
		static const wchar_t* FAILED_CREATE;

	private:
		static const UInt16 DOME_DIV_TABLE[SkyDome::QL_MAX];
		static const UInt16 PANORAMA_DIV_TABLE[SkyDome::QL_MAX];
		static const Mix::Vector3 DOME_BASE_POS;
		static const Mix::Vector3 PANORAMA_BASE_POS;
	};

}}}
