#pragma once

//! @file Utility/UI/Dialog.h
//! @brief ダイアログクラスインクルードファイル

#include <set>
#include <list>

namespace Utility{ namespace UI {

	class Manager;
	class Control;
	class Button;
	class CheckBox;
	class SliderI;
	class SliderF;
	class ComboBox;
	class Color;

	//! @class Dialog
	//! @brief ダイアログクラス
	class Dialog
	{
	private:
		struct UPDATE_EVENT_ARGS
		{
			Mix::HID::IMouse* pMouse;
			Mix::Graphics::Utility::IFont* pFont;
		};

		struct DRAW_EVENT_ARGS
		{
			Mix::Graphics::Utility::ICanvasRenderer* pCanvasRenderer;

			Mix::Vector4 borderColor;
			Mix::Vector4 backgroundColor;
			Mix::Vector4 textColor;

			Mix::Vector4 selectedBackgroundColor;
			Mix::Vector4 selectedTextColor;

			Mix::Vector4 dlgCaptionBackgroundColor;
			Mix::Vector4 dlgCaptionTextColor;

			Mix::Vector4 ctrlBackgroundColor;
			Mix::Vector4 ctrlDarkBackgroundColor;
			Mix::Vector4 ctrlDarkDarkBackgroundColor;
		};

		enum STATE_TYPE
		{
			STATE_IDLE		= 0,
			STATE_MOVE		= 1,
			STATE_REQ_CLOSE	= 2,
		};

		enum HIT_FLAG
		{
			HIT_CAPTION		= 0x00000001,
			HIT_CLOSEBUTTON	= 0x00000002,
			HIT_CLIENT		= 0x00000004,
			HIT_CONTROL		= 0x00000008,
		};

		typedef std::set<UI::Control*> ControlMap;
		typedef std::list<UI::Control*> ControlList;

		static Float32 MARGIN;

	private:
		UI::Manager* m_pManager;
		Dialog::ControlMap m_ControlMap;
		Dialog::ControlList m_ControlUpdateList;
		Dialog::ControlList m_ControlDrawList;

		Mix::StringW m_Caption;
		Mix::Vector2 m_Pos;
		Mix::Vector2 m_Size;

		Mix::RectangleF m_Rect;

		Mix::RectangleF m_CaptionRect;
		Mix::RectangleF m_CaptionTextRect;
		Mix::Vector2 m_CaptionPos;

		Boolean m_bHUDEnabled;

		Boolean m_bCloseButtonDown;
		Boolean m_bCloseButtonEnabled;
		Mix::RectangleF m_CloseButtonFrameRect;
		Mix::RectangleF m_CloseButtonRect;
		Mix::Vector2 m_CloseButtonLines[4];

		Mix::RectangleF m_BackgroundRect;

		Mix::Vector2 m_ClientPos;
		Mix::RectangleF m_ClientRect;

		UI::Control* m_pHoverControl;
		UI::Control* m_pFocusControl;

		Dialog::STATE_TYPE m_State;

		Boolean m_bClose;
		Boolean m_bActive;
		Boolean m_bDispose;

	public:
		//! @brief コンストラクタ
		Dialog( void );
		//! @brief デストラクタ
		virtual ~Dialog( void );

	public:
		//! @brief ダイアログを開きます
		//! @param[in] pManager マネージャ
		void Open( UI::Manager* pManager );

		//! @brief ダイアログを閉じます
		void Close( void );
		//! @brief ダイアログが閉じられているかどうかを取得します
		//! @return ダイアログが閉じられている場合は True を返します
		Boolean IsClose( void ) const;

		//! @brief マネージャのポインタを取得します
		//! @return マネージャのポインタを返します
		UI::Manager* GetManager( void ) const;

		//! @brief キャプションを設定します
		//! @param[in] pCaption キャプション
		void SetCaption( const wchar_t* pCaption );
		//! @brief キャプションを取得します
		//! @return キャプションを返します
		const wchar_t* GetCaption( void ) const;

		//! @brief 位置を設定します
		//! @param[in] pos 位置
		void SetPosition( const Mix::Vector2& pos );
		//! @brief 位置を取得します
		//! @return 位置を返します
		const Mix::Vector2& GetPosition( void ) const;

		//! @brief サイズを設定します
		//! @param[in] size サイズ
		void SetSize( const Mix::Vector2& size );
		//! @brief サイズを取得します
		//! @return サイズを返します
		const Mix::Vector2& GetSize( void ) const;

		//! @brief HUDを有効にするかどうかを設定します
		//! @param[in] HUDを有効にする場合は True
		//! @note この設定を有効にした場合、コントロールののみが表示されるようになります
		void SetHUDEnabled( Boolean state );
		//! @brief HUDが有効かどうかを取得します
		//! @return HUDが有効な場合は True を返します
		Boolean GetHUDEnabled( void ) const;

		//! @brief クローズボタンを有効にするかどうかを設定します
		//! @param[in] state クローズボタンを有効にする場合は Ture
		void SetCloseButtonEnabled( Boolean state );
		//! @brief クローズボタンが有効かどうかを取得します
		//! @return クローズボタンが有効な場合は True を返します
		Boolean GetCloseButtonEnabled( void ) const;

		//! @brief ダイアログが活性化されているかどうかを取得します
		//! @return 活性化されている場合は True を返します
		Boolean IsActive( void ) const;

		//! @brief ダイアログを破棄します
		void Dispose( void );
		//! @brief ダイアログが破棄されているかどうかを取得します
		//! @return 破棄されている場合は True を返します
		Boolean IsDispose( void ) const;

	protected:
		//! @brief ダイアログが開かれた際に呼び出されます
		virtual void OnOpen( void ) {}
		//! @brief ダイアログが閉じられた際に呼び出されます
		virtual void OnClose( void ) {}
		//! @brief ダイアログが破棄された際に呼び出されます
		virtual void OnDispose( void ) {}
		//! @brief ボタンがクリックされた際に呼び出されます
		//! @param[in] pButton クリックされたボタンのポインタ
		virtual void OnButton_Click( Utility::UI::Button* pButton ) {}
		//! @brief チェックボックスがクリックされた際に呼び出されます
		//! @param[in] pCheckBox クリックされたチェックボックスのポインタ
		virtual void OnCheckBox_Click( Utility::UI::CheckBox* pCheckBox ) {}
		//! @brief スライダーの値が変更された場合に呼び出されます
		//! @param[in] pSlider 値が変更されたスライダーのポインタ
		virtual void OnSlider_ValueChanged( Utility::UI::SliderI* pSlider ) {}
		//! @brief スライダーの値が変更された場合に呼び出されます
		//! @param[in] pSlider 値が変更されたスライダーのポインタ
		virtual void OnSlider_ValueChanged( Utility::UI::SliderF* pSlider ) {}
		//! @brief コンボボックスのアイテムの選択が変更された際に呼び出されます
		//! @param[in] pComboBox アイテムの選択が変更されたコンボボックスのポインタ
		virtual void OnComboBox_SelectItemChanged( Utility::UI::ComboBox* pComboBox ) {}
		//! @brief カラーの値の選択が変更された際に呼び出されます
		//! @param[in] pColor カラーの値の選択が変更されたカラーのポインタ
		virtual void OnColor_ValueChanged( Utility::UI::Color* pColor ) {}

	private:
		void Update( const Utility::UI::Dialog::UPDATE_EVENT_ARGS& args );
		void SetActive( Boolean state, Mix::HID::IMouse* pMouse );
		void AddControl( Utility::UI::Control* pControl );
		void RemoveControl( Utility::UI::Control* pControl );

		Boolean Contains( const Mix::Vector2& pos ) const;

		const Mix::RectangleF& GetRectangle( void ) const;

		void MouseMove( Mix::HID::IMouse* pMouse );
		void MouseDown( Mix::HID::IMouse* pMouse );
		void MouseUp( Mix::HID::IMouse* pMouse );
		void Draw( const Utility::UI::Dialog::DRAW_EVENT_ARGS& args );

	private:
		UInt32 HitTest( const Mix::Vector2& pos ) const;
		UI::Control* FindControl( const Mix::Vector2& pos ) const;

		friend class Manager;
		friend class Control;
		friend class Button;
		friend class CheckBox;
		friend class SliderI;
		friend class SliderF;
		friend class ComboBox;
		friend class Color;
	};
}}
