#pragma once

#include "Mix/AtomicValue.h"
#include "Mix/Scene/IManager.h"

namespace Mix{ namespace Scene{ namespace Common{

	class Renderer;
	class EffectPackage;
	class ActorLoader;
	class TerrainLoader;

	class Manager : public Mix::Scene::IManager
	{
	private:
		typedef Mix::STL::Map<Mix::Memory::SECTION_SCENE, Mix::Scene::IMaterial*, Mix::AtomicValue> UpdateMaterialMap;
		typedef Mix::STL::Vector<Mix::Memory::SECTION_SCENE, Mix::Scene::Common::Renderer*> RendererList;

	private:
		Mix::IO::IManager* m_pFileManager;
		Mix::Graphics::IDevice* m_pGraphicsDevice;

		Mix::Scene::Common::ActorLoader* m_pActorLoader;
		Mix::Scene::Common::TerrainLoader* m_pTerrainLoader;

		Manager::UpdateMaterialMap m_UpdateMaterialMap;
		Manager::RendererList m_RendererList;

	public:
		static Manager* CreateInstance( void );
		void Dispose( void );

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

		Mix::Scene::IMaterial* CreateMaterial(	Mix::Scene::Common::EffectPackage* pEffectPackage,
												Mix::IO::IReader* pReader,
												Boolean bWithMagicNumber,
												const wchar_t* pNameLabel,
												const wchar_t* pName );

	public:
		Boolean Initialize( void );

		void Update( Float32 dt );

		Mix::Scene::IMaterial* CreateMaterialWithoutMagicNumber(	Mix::Scene::Common::EffectPackage* pEffectPackage,
																	Mix::IO::IReader* pReader,
																	const wchar_t* pName );

		void AddUpdateMaterial( Mix::Scene::IMaterial* pMaterial );
		void RemoveUpdateMaterial( Mix::Scene::IMaterial* pMaterial );

		void AddRenderer( Mix::Scene::Common::Renderer* pRenderer );
		void RemoveRenderer( Mix::Scene::Common::Renderer* pRenderer );

	protected:

	public:
		virtual Boolean CreateEffectPackage( const wchar_t* pDirPath, const wchar_t* pName, Mix::Scene::IEffectPackage** ppEffectPackage );

		virtual Boolean CreateRenderer( Mix::Scene::IEffectPackage* pEffectPackage, const Mix::Scene::RENDERER_CONFIG& config, Mix::Scene::IRenderer** ppRenderer, const wchar_t* pDebugName );

		virtual Boolean CreateUniversalCamera( const Mix::Scene::CAMERA_CONFIG& config, Mix::Scene::IUniversalCamera** ppCamera, const wchar_t* pDebugName );
		virtual Boolean CreateViewCamera( const Mix::Scene::CAMERA_CONFIG& config, Mix::Scene::IViewCamera** ppCamera, const wchar_t* pDebugName );

		virtual Boolean CreateHemisphereLight( Mix::Scene::IHemisphereLight** ppLight, const wchar_t* pDebugName );
		virtual Boolean CreateDirectionalLight( Mix::Scene::IDirectionalLight** ppLight, const wchar_t* pDebugName );

		virtual Boolean CreatePointLight( Mix::Scene::IPointLight** ppLight, const wchar_t* pDebugName );
		virtual Boolean CreateSpotLight( Mix::Scene::ISpotLight** pLight, const wchar_t* pDebugName );

		virtual Boolean CreateSkyDome(	Float32 radius, Float32 height,
										Mix::Scene::ISkyDome::QUALITY heQuality,
										Mix::Scene::ISkyDome** ppSkyDome,
										const wchar_t* pDebugName );

		virtual Boolean CreateSkyDome(	Float32 radius, Float32 height,
										Mix::Scene::ISkyDome::QUALITY heQuality,
										Mix::Scene::ISkyDome::QUALITY paQuality,
										Mix::Scene::ISkyDome** ppSkyDome,
										const wchar_t* pDebugName );

		virtual Boolean CreateDefaultParticleSystem( Boolean bSimWorldSpace, Mix::Scene::IDefaultParticleSystem::PLANE_TYPE planeType, Mix::Scene::IDefaultParticleSystem** ppSystem, const wchar_t* pDebugName );
		virtual Boolean CreateBillboardParticleSystem( Boolean bSimWorldSpace, Mix::Scene::IBillboardParticleSystem** ppSystem, const wchar_t* pDebugName );

		virtual Boolean CreateLeavingParticle( Mix::Scene::IMaterial* pMaterial, Mix::Scene::IParticleSystem* pSystem, Mix::Scene::ILeavingParticle** ppParticle, const wchar_t* pDebugName );
		virtual Boolean CreateScatterParticle( Mix::Scene::IMaterial* pMaterial, Mix::Scene::IParticleSystem* pSystem, Mix::Scene::IScatterParticle** ppParticle, const wchar_t* pDebugName );

		virtual Boolean CreateFlowerPackage(	Mix::Scene::IMaterial* pMaterial,
												UInt32 numModel, const Mix::Scene::IFlowerPackage::MODEL* models,
												Mix::Scene::IFlowerPackage** ppFlowerPackage,
												const wchar_t* pDebugName );

		virtual Boolean CreatePlanter(	Mix::Scene::IFlowerPackage* pFlowerPackage,
										Mix::Scene::IPlanter** ppPlanter,
										const wchar_t* pDebugName );

		virtual Boolean CreatePlanter(	Mix::Scene::IFlowerPackage* pFlowerPackage,
										UInt32 numUnit, const Mix::Scene::IPlanter::UNIT* units,
										const Mix::Matrix4x4& worldMat,
										Mix::Scene::IPlanter** ppPlanter,
										const wchar_t* pDebugName );

		virtual Boolean CreateActorModelFromFile( Mix::Scene::IEffectPackage* pEffectPackage, const wchar_t* pFilePath, Mix::Scene::IActorModel** ppModel );
		virtual Boolean CreateActorModelFromReader( Mix::Scene::IEffectPackage* pEffectPackage, Mix::IO::IReader* pReader, Mix::Scene::IActorModel** ppModel );
		virtual Boolean CreateActorModelFromMemory( Mix::Scene::IEffectPackage* pEffectPackage, const wchar_t* pFilePath, const void* pSrc, UInt32 srcSize, Mix::Scene::IActorModel** ppModel );

		virtual Boolean CreateTerrainModelFromFile( Mix::Scene::IEffectPackage* pEffectPackage, const wchar_t* pFilePath, Mix::Scene::ITerrainModel** ppModel );
		virtual Boolean CreateTerrainModelFromReader( Mix::Scene::IEffectPackage* pEffectPackage, Mix::IO::IReader* pReader, Mix::Scene::ITerrainModel** ppModel );
		virtual Boolean CreateTerrainModelFromMemory( Mix::Scene::IEffectPackage* pEffectPackage, const wchar_t* pFilePath, const void* pSrc, UInt32 srcSize, Mix::Scene::ITerrainModel** ppModel );

		virtual Boolean CreateLightShaftsCaster( Mix::Scene::ILightShaftsCaster** ppLightShaftsCaster, const wchar_t* pDebugName );
		virtual Boolean CreateWaterPool( const Mix::Vector3& halfExtents, Mix::Vector3& worldPos, Mix::Scene::IWaterPool** ppWaterPool, const wchar_t* pDebugName );
		virtual Boolean CreateWaterPool( Mix::Scene::IWaterPoolContext* pContext, const Mix::Matrix4x4& worldMat, Mix::Scene::IWaterPool** ppWaterPool, const wchar_t* pDebugName );

		virtual Boolean CreateFloor( Mix::Scene::IFloor** ppFloor, const wchar_t* pDebugName );
		virtual Boolean CreateFloor( const Mix::Vector3& normal, Float32 offset, Mix::Scene::IFloor** ppFloor, const wchar_t* pDebugName );

		virtual Boolean CreateBasisGhost( Mix::Dynamics::IShape* pShape, Boolean bCollide, Mix::Scene::IGhost** ppGhost, const wchar_t* pDebugName );
		virtual Boolean CreateKinematicGhost( Float32 height, Float32 radius, Float32 stepHeight, Mix::Scene::IGhost** ppGhost, const wchar_t* pDebugName );

		virtual Boolean CreateMaterialFromFile( Mix::Scene::IEffectPackage* pEffectPackage, const wchar_t* pFilePath, Mix::Scene::IMaterial** ppMaterial );
		virtual Boolean CreateMaterialFromReader( Mix::Scene::IEffectPackage* pEffectPackage, Mix::IO::IReader* pReader, Mix::Scene::IMaterial** ppMaterial );
		virtual Boolean CreateMaterialFromMemory( Mix::Scene::IEffectPackage* pEffectPackage, const wchar_t* pFilePath, const void* pSrc, UInt32 srcSize, Mix::Scene::IMaterial** ppMaterial );

		virtual Boolean CreateMotionFromFile( const wchar_t* pFilePath, Mix::Scene::IMotion** ppMotion );
		virtual Boolean CreateMotionFromReader( Mix::IO::IReader* pReader, Mix::Scene::IMotion** ppMotion );
		virtual Boolean CreateMotionFromMemory( const wchar_t* pFilePath, const void* pSrc, UInt32 srcSize, Mix::Scene::IMotion** ppMotion );

		virtual const Mix::Vector4& Debug_GetDrawColor( Mix::Scene::DEBUG_DRAW_COLOR_TYPE type ) const;
		virtual void Debug_SetDrawColor( Mix::Scene::DEBUG_DRAW_COLOR_TYPE type, const Mix::Vector4& color );

	private:
		static const wchar_t* MSG_NOT_SUPPORT_SHADERMODEL;
		static const wchar_t* MSP_EP_NOT_SUPPORT_RENDERER;
		static const wchar_t* MSP_EP_NOT_SUPPORT_MATERIAL;
	};

}}}
