#pragma once

namespace nlite{
	

	///
	///ウィンドウ名
	///
	const static LPCTSTR NLITE_MAINWINDOW = TEXT("nlite");

	
	
	///
	///メインフレームクラス
	///
	class CNliteMainFrame : public CFrameWindowImpl<CNliteMainFrame>
		,public CUpdateUI<CNliteMainFrame>,public CMessageFilter, public CIdleHandler
	{
		
	public:

		
		class CLiveUserData;
		friend CLiveUserData;

		struct LvnoSearchFunctional;

		///
		///放送番号入力用
		///
		class CSubLiveNoComboBox:public CWindowImpl<CEdit>{
			friend CNliteMainFrame;

		public:
			//視聴履歴表示用ペア
			typedef std::pair<CNLiteString,CNLiteString> LiveInfo;
			typedef std::list<LiveInfo> LiveInfoList;

		private:
			CNliteMainFrame &self;						//メインフレームウィンドウ
			CComAutoCriticalSection cs;					//クリティカルセクションオブジェクト
			BOOL untilConnectingFlag;					//接続処理中かのフラグ判定
			LiveInfoList liveInfoList;					//放送履歴情報
		public:
			
			///
			///コンスタラクタ
			///
			CSubLiveNoComboBox(CNliteMainFrame &in_self);
			

			//メッセージループ
			BEGIN_MSG_MAP_EX(CSubLiveNoComboBox)
				MSG_WM_MOUSEWHEEL(OnMouseWheel)
				MSG_WM_KEYDOWN(OnKeyDown)
			END_MSG_MAP()

		public:

			///
			///放送情報追加
			///
			VOID AddLiveInfo(CNicoLiveStream &stream,LvnoSearchFunctional &functional);
			

			///
			///放送番号入力を許可する
			///
			VOID AgreeInputLvNo();


		private:
			///
			///キー押下時の処理
			///
			VOID OnKeyDown(TCHAR wParam, UINT upLParam,UINT loLParam);


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

		};


		
		struct LvnoSearchFunctional{
			LPCTSTR lvNo;											
			CNLiteString dispData;									

			LvnoSearchFunctional(LPCTSTR in_lvNo):lvNo(in_lvNo){}

			bool operator()(CSubLiveNoComboBox::LiveInfo &listInfo){
				return listInfo.second == lvNo;
			}

		};


		///
		///コメント受信
		///
		class CLiveUserData {


			friend CNliteMainFrame;
		private:

			CNliteMainFrame &self;
			

		public:

			///
			///コンストラクタ
			///
			CLiveUserData(CNliteMainFrame &self);
			

			///
			///接続開始時処理
			///
			VOID OnConnect();
			
			///
			///コメント受信開始時のコールバック処理
			///
			VOID OnChatReceveStart(CNicoLiveStream &stream,NicoLiveThreadComment_P threadComment);


			///
			///1コメント受信した時のコールバック処理
			///受信したコメントをバッファに格納
			///
			VOID OnChatReceve(NicoLiveChat_P chat,UINT_PTR count);
			

			///
			///チャット受信確定時のコールバック処理
			///主に受信したコメントの描画処理を行う
			///
			VOID OnChatReceveSettle(UINT_PTR commentCount,UINT_PTR commentCountSum);

			///
			///コメント送信結果受信時のコールバック処理
			///
			VOID OnChatSendResult(NicoLiveSendResultComment_P sendResult);


			///
			///ハートビート送信時のコールバック
			///
			VOID OnHeartBeat(NicoLiveHeartBeat_P heartBeat);


			///
			///切断時のコールバック
			///
			VOID OnDisconnect();

		};

		friend CSubLiveNoComboBox;
	public:

		typedef CFrameWindowImpl<CNliteMainFrame> baseWindow;

		// ウィンドウクラス名、共通リソースID、スタイル、背景色を登録
		DECLARE_FRAME_WND_CLASS(NLITE_MAINWINDOW, IDC_NLITE)

	private:
		CCommentView commentView;									//コメント表示ウィンドウ
		CStatusBarCtrl statusBar;									//ステータスバー
		CLiveUserData userData;										//イベントハンドラ用クラス
		CSubLiveNoComboBox subLiveNoComboBox;						//生放送番号入力用コンボボックス(サブクラス)
		CCommentWriteWindow commentWriteWindow;						//コメント書き込み用クラス
		CTabCtrl tabctrl;											//タブコントロール
		HFONT hTabFont;												//タブウィンドウ用のフォント				
		CComboBoxEx lvNoCombo;										//生放送番号入力用コンボボックス
		INT_PTR statusBarHeight;									//ステータスバーの高さ
		INT_PTR toolBarHeight;										//ツールバーの高さ
		CNicoVideoAuth nicoVideoAuth;								//ニコニコ動画認証用オブジェクト
		CNicoLiveStream nicoLiveStream;								//ニコニコ生放送オブジェクト
		CMultiPaneStatusBarCtrl m_hStatusBar;						//マルチペインステータスバー
		CProgressBarCtrl  m_progresBar;								//プログレスバー
		CListenerSettingWindow listenerSettingWindow;				//リスナー設定ウィンドウ
		CComAutoCriticalSection	lvNoBufCS;							//生放送番号クリティカルセクション
		CString lvNoBuffer;											//生放送番号バッファ
	private:
		// メッセージフィルタ処理
		virtual BOOL PreTranslateMessage(MSG* pMsg);

		// アイドル処理
		virtual BOOL OnIdle();

		
		

	public:

		///
		///コンストラクタ
		///
		CNliteMainFrame();
		

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

		
		BEGIN_UPDATE_UI_MAP(CNliteMainFrame)
			// エントリなし
		END_UPDATE_UI_MAP()
		
		// メッセージマップ
		BEGIN_MSG_MAP_EX(CNliteMainFrame)
			MSG_WM_CREATE(OnCreate)
			MSG_WM_CLOSE(OnClose)
			MSG_WM_DESTROY(OnDestroy)
			MESSAGE_HANDLER(WM_SIZE,OnSize)
			MSG_WM_SIZING(OnSizing)
			MESSAGE_HANDLER(WM_SETCURSOR,OnSetCursor)
			MESSAGE_HANDLER_EX(UM_CLICK_CHATNO,OnClickChatNo)
			MESSAGE_HANDLER_EX(UM_UPDATEUI,OnUpDateUI)
			MESSAGE_HANDLER_EX(UM_UNLOCK_LVNOBUFFER,OnUnlockLvNoBuffer)
			MESSAGE_HANDLER_EX(UM_CLICK_USERNAME,OnClickUserName)
			COMMAND_ID_HANDLER_EX(IDM_EXIT, OnMenuExit)
			COMMAND_ID_HANDLER_EX(IDM_ABOUT,OnMenuAbount)
			COMMAND_ID_HANDLER_EX(IDM_SPEAK_COMMENT_CHECK,OnSpeakCommentCheck)
			COMMAND_ID_HANDLER_EX(IDM_FRONT_WINDOW_CHECK,OnFrontWindowCheck)
			COMMAND_ID_HANDLER_EX(IDM_COOKIE,OnCookie)
//			COMMAND_ID_HANDLER_EX(IDM_VIEW_PREFERENCE,OnViewPreference)
			COMMAND_CODE_HANDLER_EX(CBN_SELCHANGE,OnCbSelChange)
			NOTIFY_HANDLER(ATL_IDW_TOOLBAR,RBN_HEIGHTCHANGE,OnRbnHeightChange)
			// CFrameWindowImplクラスへチェーン
			CHAIN_MSG_MAP(CFrameWindowImpl<CNliteMainFrame>)
		END_MSG_MAP()

		
		///
		///初期化処理
		///
		VOID Initialize(LPCTSTR localAppDataPath);
		
		///
		///終了処理
		///
		VOID Finalaize();
		
		
		///
		///例外発生時の処理
		///
		VOID OnException();


	private:
		///
		///メニューアイテムがチェックされているかの判定
		///
		BOOL IsMenuItemChecked(UINT item);

		///
		///メニューアイテムのチェック状態を変更
		///
		VOID SetMenuItemCheck(UINT item,BOOL state);

	private:

		///
		///ウィンドウを閉じるときの処理
		///
		VOID OnClose();

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

		///
		///ツールバー高さ変更
		///
		LRESULT OnRbnHeightChange(INT_PTR wParam,LPNMHDR lParam,BOOL &bHandled);
		

		///
		///このウィンドウのUI更新
		///
		LRESULT OnUpDateUI(UINT uMsg,WPARAM wParam,LPARAM lParam);

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

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


		///
		///サイズ変更中処理
		///
		VOID OnSizing(UINT wParam,LPRECT lParam);
		
		///
		///サイズ変更後
		///
		LRESULT OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL& bHandled);
		
		
		///
		///子ウィンドウサイズ変更処理
		///
		VOID ChangeSize(const SIZE& client);

		///
		///コンボボックスの選択項目が変更された
		///
		LRESULT OnCbSelChange(UINT hiWparam,int loWparam,HWND lParam);

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


		///
		///ニコ生放送に接続
		///
		BOOL ConnectNicoLive(LPCTSTR liveNo);


		///
		///マウスカーソル変更処理
		///
		LRESULT OnSetCursor(LRESULT msg,WPARAM wParam,LPARAM lParam,BOOL &bHandled);


		//メニューからファイルを終了を選択
		VOID OnMenuExit(UINT uNotifyCode, int nID, HWND hWndCtl);

		//メニューのアプリケーションバージョン情報表示
		VOID OnMenuAbount(UINT uNotifyCode,int nID,HWND hWndCtl);

		//クッキーの設定
		VOID OnCookie(UINT uNotifyCode,int nID,HWND hWndCtl);

		///
		///コメント読み上げチェッククリック時の動作
		///
		VOID OnSpeakCommentCheck(UINT uNotifyCode,int nID,HWND hWndCtl);
		
		///
		///最前面表示チェッククリック時の動作
		///
		VOID OnFrontWindowCheck(UINT uNotifyCode,int nID,HWND hWndCtl);

		//ビューア設定
		VOID OnViewPreference(UINT uNotifyCode,int nID,HWND hWndCtl);

		///
		///生放送番号バッファのロックを解除
		///
		LRESULT OnUnlockLvNoBuffer(UINT uMsg,WPARAM wParam,LPARAM lParam);


		///
		///CNicoLiveStreamのコールバック用関数
		///
		static NLIB_RESULT LiveCallBack(NICOLIVE_EVENT eventType,NicoLiveStream_P pNicoLiveStream,LPVOID option,NICOLIVE_PARAM param1,NICOLIVE_PARAM param2);

		
		///
		///接続スレッド
		///
		static VOID ConnectingThread(LPVOID userData);
	};




	

}