#pragma once

namespace nlite{

	class CCommentView;
	class CCommentListWindow;
	class CChatChildCtrlsList;
	class CChatChildCtrls;

	//定数用の名前空間
	namespace commentViewConstant{

		//コメントビューウィンドウ名
		const static LPCTSTR  NLITE_COMMENTVIEW = TEXT("NLITE_COMMENTVIEW");

		//コメントリストウィンドウ名
		const static LPCTSTR NLITE_COMMENTLISTWINDOW = TEXT("NLITE_COMMENTLISTWINDOW");

		//ヘッダーの高さ
		const static UINT_PTR HEADER_HAIGHT = 20;

		//ヘッダーコントロールID
		const static UINT_PTR HEADER_ID = 257;

		//コメントリストウィンドウID
		const static UINT_PTR LISTWINDOW = 258;

		//baseWindowID
		const static UINT_PTR MENU_OR_ID = 256;
	}

	class CChatReadEdit :public CWindowImpl<CChatReadEdit,CRichEditCtrl>{
		friend CCommentListWindow;
		friend CChatChildCtrls;

		CCommentView &m_master;


		BEGIN_MSG_MAP(CChatReadEdit)

		END_MSG_MAP()
		CChatReadEdit(CCommentView &m_master);
		BOOL SetWindowText(const CChatData &str);

		///
		///内容をリセット
		//
		VOID Reset();


		///
		///リンク表示文字列を決定
		///
		VOID linkStringBeside(const tstring &target,const nliteregex::tregex &re);


		///
		///このアプリケーションにおける汎用的なウィンドウ作成関数
		///
		HWND GeneralCreate(HWND hParent,DWORD eventMask,UINT id);
	};

	class CChatChildCtrls{
		friend CCommentListWindow;
		friend CChatChildCtrlsList;
	private:
		CChatReadEdit chatDispCtrl;
		CCommentView &m_master;


	private:

		enum {
			NO_DIOSCTRL_ID = 10000000,
			USERNAME_DISPCTRL_ID = 20000000,
			CHAT_DISPCTRL_ID = 30000000

		};

		///
		///コンストラクタ
		///
		CChatChildCtrls(CCommentView &hMaster);

		///
		///指定した高さにコントロールをセット
		///
		VOID SetCtrl(HDWP,const RECT &rc,CCommentList::reference commen,BOOL mulutiLineFlag);

		VOID AdjustRect(RECT &rc);

		VOID Hide(HDWP hdwp);

		VOID Create();

		///
		///コントロールの個数を取得
		///
		static UINT_PTR GetCtrlCount();



	};

	///
	///コメント表示ウィンドウの子ウィンドウリスト
	///
	class CChatChildCtrlsList{
		friend CCommentView;
		friend CCommentListWindow;
		friend CChatChildCtrls;

	private:
		typedef std::list<CChatChildCtrls> InternalList;

		InternalList m_list;								//内部で管理するリスト
		CCommentView &m_hMaster;							//このウィンドウを所有している親ウィンドウ


	private:
		typedef InternalList::reference reference;
		typedef InternalList::iterator iterator;

		///
		///コンストラクタ
		///
		CChatChildCtrlsList(CCommentView &hMaster);



		///
		///コントロールを表示
		///
		VOID ShowCntrls();

		///
		///非表示処理
		///
		VOID AllHide();

	private:

		///
		///拡張処理
		///
		iterator Extend();


	};


	//コメント表示用ウィンドウ
	class CCommentListWindow:public CWindowImpl<CCommentListWindow>{

		friend CCommentView;
		friend CChatChildCtrls;
		friend CChatChildCtrlsList;


		//メンバ
	private:
		CCommentView &self;
		UINT_PTR viewSellHeight;
		CPen collLinePen;													//項目縦線描画用ペン
		CPen normalSellLinePen;												//枠線描画用ペン
		CBrush normalBkBrush;												//背景描画用ブラシ
		CPen selectSellLinePen;												//枠線描画用ペン
		CBrush selectBkBrush;												//背景描画用ブラシ
		CFont linkFont;														//リンク文字列のフォント


		enum {
			CALCEDIT_ID = 100

		};

	public:


		DECLARE_WND_CLASS(commentViewConstant::NLITE_COMMENTLISTWINDOW)


		//
		//メッセージマップ
		//
		BEGIN_MSG_MAP(CCommentListWindow)
			MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
			MSG_WM_LBUTTONDOWN(OnLButtonDown)
			MSG_WM_CREATE(OnCreate)
			MSG_WM_ERASEBKGND(OnEraseBkGnd)
			MSG_WM_MOUSEWHEEL(OnMouseWheel)
			MSG_WM_PAINT(OnPaint)
			MSG_WM_SIZE(OnSize)
			MSG_WM_KEYDOWN(OnKeyDown)
			MSG_WM_SETCURSOR(OnSetCursor)
			MESSAGE_HANDLER_EX(UM_COMMENTVIEW_SETCTRL,OnSetCtrol)
			NOTIFY_ID_HANDLER_EX(CChatChildCtrls::CHAT_DISPCTRL_ID,OnChatControlNortify)
			NOTIFY_HANDLER_EX(CALCEDIT_ID,EN_REQUESTRESIZE,OnCalcSellSize)
		END_MSG_MAP()



	private:

		///
		///コンストラクタ
		///
		CCommentListWindow(CCommentView &self_in);

		///
		///デストラクタ
		///
		~CCommentListWindow();




		///
		///プロパティ設定時の処理
		///
		VOID OnSetProperty();

		///
		///スクロールページ計算
		///
		UINT_PTR CalcScrollPage(UINT_PTR nMax);

		///
		///行の高さを問い合わせ
		///
		VOID CalcItemHeight(CChatData &chatData);

		///
		///選択行を表示
		///
		VOID ShowCurSel();

		///
		///チャット文字列表示領域計算
		///
		VOID CalcChatRect(const CDC &cdc,RECT &rc,const CNLiteString &str);


		//プライベート関数
	private:

		///
		///アイテム描画
		///
		VOID DrawItem(CDC &dc,const RECT &rc,const RECT *headerRect,CChatData &chatData);

		///
		///描画高さをリセット
		///
		VOID ResetViewSellHeight();




		///
		///クリックした行を計算
		///
		CCommentList::iterator CalcClickLine(INT_PTR height);

		///
		///ユーザ名かコメ番上かの判定
		///
		BOOL IsOnNoOrUserName(UINT_PTR index,const POINT &point);

		//メッセージハンドラ
	private:

		///
		///ウィンドウ作成時の処理
		///
		LRESULT OnCreate(LPCREATESTRUCT lpCreateStruct);

		///
		///マウスクリック時の処理
		///
		VOID OnLButtonDown(UINT wParam, _WTYPES_NS::CPoint &point);

		///
		///破棄時の処理
		///
		VOID OnDestroy();

		///
		///描画処理
		///
		VOID OnPaint(HDC hdc);

		///
		///コントロールセット処理
		///
		LRESULT OnSetCtrol(UINT uMsg,WPARAM wparam,LPARAM lparam);

		///
		///サイズ変更
		///
		VOID OnSize(UINT wParam, _WTYPES_NS::CSize &windowSize);

		///
		///マウスダブルクリック時の処理
		///
		VOID OnLButtonDblClk(UINT wParam, _WTYPES_NS::CPoint &point);

		///
		///背景塗りつぶし
		///
		LRESULT OnEraseBkGnd(HDC lparam);

		///
		///マウスホイール
		///
		LRESULT OnMouseWheel(UINT loWparam,SHORT hiWparam,CPoint &point);

		///
		///キー押下時の処理
		///
		VOID OnKeyDown(TCHAR vKey,UINT loLParam,UINT hiLParam);

		///
		///カーソル変更処理
		///
		LRESULT OnSetCursor(HWND wparam,UINT loLparam,UINT hiLparam);

		///
		///チャットコントロール通知
		///
		LRESULT OnChatControlNortify(LPNMHDR lParam);


		///
		///セルのサイズを計算
		///
		LRESULT OnCalcSellSize(LPNMHDR lParam);

	};

	///
	///コメントビュークラス
	///
	class CCommentView:public CWindowImpl<CCommentView>{
		friend CChatChildCtrls;
		friend CCommentListWindow;						//フレンド宣言
		friend CChatChildCtrlsList;
		friend CChatChildCtrls;
		friend CChatReadEdit;
		//プライベート型・クラス定義
	private:

		//ヘッダー情報格納用オブジェクト
		typedef struct{

			LPTSTR *columns;
			UINT_PTR *holizensize;
			UINT_PTR count;

		}HEADERSINFO,*LPHEADERSINFO;






		//メンバ宣言
	private:

		CHeaderCtrl m_header;						//ヘッダーコントロール
		CCommentListWindow  m_commentListWindow;	//コメントリストウィンドウ
		CNicoLiveStream &stream;					//放送オブジェクト
		GeneralProperty generalProperty;			//一般設定
		CCommentList commentlist;					//コメントリスト
		CommentViewProperty viewproperty;			//表示プロパティ
		HFONT hHeaderFontNew;						//ヘッダーフォント
		CNicoVideoAuth &refAuth;					//ニコニコ生放送認証オブジェクト参照
		CChatChildCtrlsList chatChildCtrlsList;		//子ウィンドウリスト








	public:

		enum{
			NO,
			USERNAME,
			COMMENT,
			TIME,
			INFO

		};

		///
		///コンストラクタ
		///
		CCommentView(CNicoLiveStream &stream,CNicoVideoAuth &refAuth);

		///
		///デストラクタ
		///
		~CCommentView();

		///
		///ウィンドウ更新
		///
		VOID UpDateUI();


		//
		//ウィンドウクラス宣言
		//
		DECLARE_WND_CLASS_EX(commentViewConstant::NLITE_COMMENTVIEW,0,COLOR_BACKGROUND)

		//
		//メッセージマップ
		//
		BEGIN_MSG_MAP(CCommentView)
			MSG_WM_CREATE(OnCreate)
			MSG_WM_DESTROY(OnDestroy)			
			MSG_WM_SIZE(OnSize)
			MSG_WM_HSCROLL(OnHScroll)
			MSG_WM_VSCROLL(OnVScroll)
			MESSAGE_HANDLER_EX(UM_CLICK_CHATNO,OnClickChatNo)
			MESSAGE_HANDLER_EX(UM_CLICK_USERNAME,OnClickUserName)
			MSG_WM_ERASEBKGND(OnEraseBkgnd)
			NOTIFY_CODE_HANDLER_EX(HDN_ENDTRACK   ,OnHeaderEndTrack)
			NOTIFY_CODE_HANDLER_EX(HDN_ENDDRAG  ,OnHeaderEndDrag)
		END_MSG_MAP()

		///
		///プロパティ設定
		///
		VOID SetProperty(const CommentViewProperty &setProperty,const GeneralProperty &in_generalProperty);

		///
		///プロパティ取得
		///
		CommentViewProperty &GetProperty();

		///
		///ウィンドウ作成
		///
		HWND Create(HWND hWndParent);

		///
		///ヘッダの横幅取得
		///
		UINT_PTR GetColumnHolSizeSum();

		///
		///ニコ生に接続時の処理
		///
		VOID OnConnect();

		///
		///チャットコメント受信時の処理
		///
		VOID OnChatReceve(NicoLiveChat_P chat,UINT_PTR count);

		///
		///チャットコメント受信確定処理
		///
		VOID OnChatReceveSettle(UINT_PTR commentCount,UINT_PTR commentCountSum);



		//プライベート関数
	private:


		///
		///ヘッダ追加
		///
		VOID AddHeader(LPHEADERSINFO infos);

		///
		///ヘッダの横幅決定
		///
		VOID DecisionHorzSize();


		///
		///サイズ変更処理
		///
		VOID ChangeSize(const SIZE& client);

		//ウィンドウメッセージハンドラ
	private:



		///
		///サイズ変更後処理
		///
		LRESULT OnSize(UINT wParam,SIZE lParam);



		///
		///ビューアに表示されているコメ番がクリックされた時の処理
		///
		LRESULT OnClickChatNo(UINT uMsg,WPARAM wParam,LPARAM lParam);


		///
		///ビューアに表示されているユーザ名がクリックされた時の処理
		///
		LRESULT OnClickUserName(UINT uMsg,WPARAM wParam,LPARAM lParam);


		///
		///背景塗りつぶし処理
		///
		LRESULT OnEraseBkgnd(HDC wParam);

		///
		///ウィンドウ破棄時の処理
		///
		VOID OnDestroy();

		///
		///ヘッダアイテム変更時処理
		///
		LRESULT OnHeaderEndTrack(LPNMHDR lParam);


		///
		///ヘッダドラッグ後処理
		///
		LRESULT OnHeaderEndDrag(LPNMHDR lParam);



		///
		///横スクロール時の処理
		///
		VOID OnHScroll(INT_PTR loWParam,SHORT hiWParam,HWND lParam);

		///
		///縦スクロール時の処理
		///
		VOID OnVScroll(INT_PTR loWParam,SHORT hiWParam,HWND lParam);

		///
		///作成時の処理
		///
		LRESULT OnCreate(LPCREATESTRUCT lpcs);

	};

}
