#pragma once

#include <list>
#include <vector>
#include <string>

#include "Mix/Tool/Win32/Core/Object.h"
#include "Mix/Tool/Win32/Core/Graphics/LineHelper.h"

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{
	class World;
}}}}

namespace Mix{ namespace Tool{ namespace Win32{ namespace Dynamics{ namespace Design{
	class Actor;
}}}}}

namespace Mix{ namespace Tool{ namespace Win32{ namespace Graphics{

	class Manager;
	class SwapChain;
	class Texture;
	class TargetTexture;
	class CubeTexture;
	class Camera;
	class SceneObject;
	class DrawObject;

	class Scene : public Mix::Tool::Win32::Object
	{
	private:
		enum VALUE
		{
			COLOR_TEX_MAX = 2,
		};

		struct GRID_PARAM
		{
			float pitch;
			float extent;
		};

		class DepthTextureHelper
		{
		private:
			enum VALUE { TEX_MAX = 2, };

		private:
			unsigned int m_CurrentIndex;
			unsigned int m_NextIndex;
			Mix::Tool::Win32::Graphics::TargetTexture* m_pTex[DepthTextureHelper::TEX_MAX];

		public:
			DepthTextureHelper( void );
			~DepthTextureHelper( void );

			bool Initialize( D3DFORMAT d3dFormat );

			void Flip( void );

			Mix::Tool::Win32::Graphics::Texture* GetCurrentPtr( void );
			Mix::Tool::Win32::Graphics::Texture* GetNextPtr( void );
		};

		typedef std::list<Mix::Tool::Win32::Graphics::Camera*> CameraList;

	private:
		Mix::Tool::Win32::Graphics::Texture* m_pColorTex;
		Scene::DepthTextureHelper* m_pDepthTex;
		Mix::Tool::Win32::Graphics::Texture* m_pRefractTex;

		Scene::CameraList m_CameraList;

		D3DXVECTOR4 m_BackgroundColor;

		D3DXVECTOR4 m_GridColor;
		GRID_PARAM m_GridParam;
		std::vector<Mix::Tool::Win32::Graphics::LINE_VERTEX> m_GridLineList;

		D3DXVECTOR4 m_TextColor;
		D3DXVECTOR4 m_ViewVolumeColor;
		D3DXVECTOR4 m_BoneColor;

		D3DXVECTOR4 m_KinematicCharacterColor;
		D3DXVECTOR4 m_SensorColor;
		D3DXVECTOR4 m_CollisionColor;
		D3DXVECTOR4 m_JointAxisColor;
		D3DXVECTOR4 m_JointBallColor;
		D3DXVECTOR4 m_JointLimitColor;
		float m_JointScale;

		D3DXVECTOR4 m_SelectedColor;
		float m_AxisScale;

		D3DXVECTOR4 m_LightAmbientColor;
		D3DXVECTOR4 m_LightDiffuseColor;
		D3DXVECTOR3 m_LightDirection;
		D3DXMATRIX m_LightPoseMatrix;
		D3DXQUATERNION m_LightPoseQuat;

		float m_LightDrawScale;
		std::vector<Mix::Tool::Win32::Graphics::LINE_VERTEX> m_LightArrow;
		std::vector<Mix::Tool::Win32::Graphics::LINE_VERTEX> m_LightLine;

		Mix::Tool::Win32::Graphics::DrawObject* m_pDrawObject;
		Mix::Tool::Win32::Dynamics::Design::Actor* m_pDynamicsActorDesigner;
		Mix::Tool::Win32::Dynamics::World* m_pDynamicsWorld;

		std::wstring m_ReflectionTexFilePath;
		Mix::Tool::Win32::Graphics::CubeTexture* m_pRelrectionTex;

		Mix::Tool::Win32::Graphics::LineHelper m_LineHelper;

		std::vector<Mix::Tool::Win32::Graphics::OPACITY_SUBSET> m_OpacitySubsets;
		std::vector<Mix::Tool::Win32::Graphics::TRANSPARENCY_SUBSET> m_TransparencySubsets;
		std::vector<Mix::Tool::Win32::Graphics::REFRACT_SUBSET> m_RefractSubsets;
		std::vector<Mix::Tool::Win32::Graphics::OPACITY_SUBSET> m_SelectMapSubsets;
		std::vector<Mix::Tool::Win32::Graphics::TRANSPARENCY_SUBSET> m_SelectColorSubsets;

		unsigned int m_DrawPrimitiveCount;

	private:
		void OnUpdate( void );
		void OnRefresh( void );
		bool OnDraw( void );

	private:
		void BeginDraw( Mix::Tool::Win32::Graphics::Camera* pCamera );
		void EndDraw( void );

		void DrawSelectMap(	Mix::Tool::Win32::Graphics::Manager* pManager,
							Mix::Tool::Win32::Graphics::Camera* pCamera );

		void DrawColor( Mix::Tool::Win32::Graphics::Manager* pManager,
						Mix::Tool::Win32::Graphics::Camera* pCamera,
						Mix::Tool::Win32::Graphics::SwapChain* pSwapChain );

		void CommitTransform( Mix::Tool::Win32::Graphics::Manager* pManager, const Mix::Tool::Win32::Graphics::Camera* pCamera, const Mix::Tool::Win32::Graphics::BASE_SUBSET* pSubset );
		void CommitMaterial( Mix::Tool::Win32::Graphics::Manager* pManager, Mix::Tool::Win32::Graphics::Material* pMaterial );
		void DrawSubset( Mix::Tool::Win32::Graphics::Manager* pManager, const Mix::Tool::Win32::Graphics::BASE_SUBSET* pSubset, bool bCountPrmitive = true );

		void UpdateLightDir( const D3DXMATRIX& mat );
		void UpdateGridLineList( void );

	public:
		Scene( void );
		virtual ~Scene( void );

		bool Initialize( void );

		const D3DXVECTOR4& GetBackgroundColor( void ) const;
		void SetBackgroundColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetGridColor( void ) const;
		void SetGridColor( const D3DXVECTOR4& color );

		float GetGridPitch( void ) const;
		void SetGridPitch( float pitch );

		float GetGridExtent( void ) const;
		void SetGridExtent( float extent );

		const D3DXVECTOR4& GetTextColor( void ) const;
		void SetTextColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetViewVolumeColor( void ) const;
		void SetViewVolumeColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetBoneColor( void ) const;
		void SetBoneColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetKinematicCharacterColor( void ) const;
		void SetKinematicCharacterColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetSensorColor( void ) const;
		void SetSensorColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetCollisionColor( void ) const;
		void SetCollisionColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetJointAxisColor( void ) const;
		void SetJointAxisColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetJointBallColor( void ) const;
		void SetJointBallColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetJointLimitColor( void ) const;
		void SetJointLimitColor( const D3DXVECTOR4& color );

		float GetJointScale( void ) const;
		void SetJointScale( float scale );

		const D3DXVECTOR4& GetSelectedColor( void ) const;
		void SetSelectedColor( const D3DXVECTOR4& color );

		float GetAxisScale( void ) const;
		void SetAxisScale( float scale );

		bool AddCamera( Mix::Tool::Win32::Graphics::Camera* pCamera );
		bool RemoveCamera( Mix::Tool::Win32::Graphics::Camera* pCamera );

		void ResetLightPoseMatrix( void );
		const D3DXMATRIX& GetLightPoseMatrix( void ) const;
		void SetLightPoseMatrix( const D3DXMATRIX& mat );
		const D3DXQUATERNION& GetLightPoseQuat( void ) const;
		void SetLightPoseQuat( const D3DXQUATERNION& quat );
		const D3DXVECTOR3& GetLightDirection( void ) const;

		const D3DXVECTOR4& GetLightAmbientColor( void ) const;
		void SetLightAmbientColor( const D3DXVECTOR4& color );

		const D3DXVECTOR4& GetLightDiffuseColor( void ) const;
		void SetLightDiffuseColor( const D3DXVECTOR4& color );

		float GetLightShading( void ) const;
		void SetLightShading( float shading );

		float GetLightDrawScale( void ) const;
		void SetLightDrawScale( float scale );

		const wchar_t* GetReflectionTexture( void ) const;
		void SetReflectionTexture( const wchar_t* pFileName );

		Mix::Tool::Win32::Graphics::DrawObject* GetDrawObject( void ) const;
		void SetDrawObject( Mix::Tool::Win32::Graphics::DrawObject* pDrawObject );

		Mix::Tool::Win32::Dynamics::Design::Actor* GetDynamicsActorDesigner( void ) const;
		void SetDynamicsActorDesigner( Mix::Tool::Win32::Dynamics::Design::Actor* pDynamicsActorDesigner );

		Mix::Tool::Win32::Dynamics::World* GetDynamicsWorld( void ) const;
		void SetDynamicsWorld( Mix::Tool::Win32::Dynamics::World* pDynamicsWorld );

	public:
		virtual Mix::Tool::Win32::Object::TYPE GetType( void ) const;
		virtual bool QueryType( Mix::Tool::Win32::Object::TYPE type ) const;

	private:
		static const D3DXVECTOR4 DEF_BACKGROUND_COLOR;
		static const D3DXVECTOR4 DEF_GRID_COLOR;
		static const float DEF_GRID_PITCH;
		static const float DEF_GRID_EXTENT;
		static const D3DXVECTOR4 DEF_TEXT_COLOR;
		static const D3DXVECTOR4 DEF_VIEWVOLUME_COLOR;
		static const D3DXVECTOR4 DEF_BONE_COLOR;
		static const D3DXVECTOR4 DEF_KC_COLOR;
		static const D3DXVECTOR4 DEF_SENSOR_COLOR;
		static const D3DXVECTOR4 DEF_COLLISION_COLOR;
		static const D3DXVECTOR4 DEF_JAXIS_COLOR;
		static const D3DXVECTOR4 DEF_JBALL_COLOR;
		static const D3DXVECTOR4 DEF_JLIMIT_COLOR;
		static const float DEF_JSCALE;
		static const D3DXVECTOR4 DEF_SELECTED_COLOR;
		static const float DEF_AXIS_SCALE;
		static const D3DXVECTOR4 DEF_GLOBAL_AMBIENT_COLOR;
		static const D3DXVECTOR4 DEF_DIR_LIGHT_COLOR;
		static const float DEF_DIR_LIGHT_LINE_Z;
		static const float DEF_DIR_LIGHT_DRAW_SCALE;
		static const float DEF_DIR_LIGHT_ROT_X;
		static const float DEF_DIR_LIGHT_ROT_Y;
		static const D3DXVECTOR4 DIR_LIGHT_VERTEX_TABLE[4];
		static const unsigned int DIR_LIGHT_INDEX_TABLE[6][2];

		friend class Manager;
		friend class SceneObject;
	};

}}}}
