#pragma once

namespace nlite{

	//前方宣言
	class CCommentListWindow;

	//国コード
	namespace cuntry{

		enum LOCALE{
			unknown,
			jp

		};

	}

	///
	///リスナーデータ
	///
	struct ListenerData{
	private:

	public:
		CNLiteString user_id;					//ユーザーID
		CNLiteString name;						//ユーザー名
		CNLiteString community;					//登録したコミュニティ
		COLORREF bgcolor;						//背景色
		COLORREF nameColor;						//名前色
		time_t time;							//登録時間
		BOOL onlyCommunityFlag;
	public:

		enum {
			INIT_COLOR = -1

		};
		
		///
		///コンストラクタ
		///
		ListenerData();

		///
		///背景色設定
		///
		VOID SetBkColor(COLORREF bkColor_in);

		///
		///名前食設定
		///
		VOID SetNameColor(COLORREF nameColor_in);
		
		///
		///ユーザ名設定
		///
		VOID SetUserName(LPCTSTR name);
	};

	//
	//リスナーデータから背景カラー収集ファンクショナル
	//
	class CListenerColorCollector{

	private:
		std::deque<COLORREF> colorlist;										//色リスト

	public:

		typedef std::deque<COLORREF>::iterator iterator;

		//指定した色が登録されているか調べる
		BOOL Find(COLORREF target){

			iterator end = colorlist.end();

			return std::find(colorlist.begin(),end,target) != end ? TRUE : FALSE;
		}

		//ファンクショナル
		void operator()(ListenerData &target){

			if(target.bgcolor != ListenerData::INIT_COLOR){

				colorlist.push_back(target.bgcolor);
			}

		}

	};
	
	
	///
	///リスナーリスト
	///
	class CListenerList{

	private:
		typedef ListenerData InternalType;
		typedef std::list<InternalType> ListenerList_Internal; 
		ListenerList_Internal m_listenerList;

	public:

		typedef InternalType& reference;
		typedef ListenerList_Internal::value_type value_type;
		typedef ListenerList_Internal::iterator iterator;

		

		///
		///ユーザー登録
		///
		reference Register(ListenerData &listener,BOOL bUpdate);


		///
		///リスナーデータ読み込み
		///
		BOOL ReadProperty(LPCTSTR fileName);

		///
		///リスナーデータ書き込み
		///
		BOOL WriteProperty(LPCTSTR fileName);

		
		///
		///背景色を収集する
		///
		VOID BkColorCollect(CListenerColorCollector &target);

	};

	

	class CChatData{

		
	public:
		struct ViewData{

			//色コード初期値
			enum{
				INIT_COLOR = -1
			};

			BOOL selectFlag;					//選択状態
			COLORREF stringColor;				//独自文字色
			COLORREF backColor;					//独自背景色
			COLORREF sellLineColor;				//枠線色
			UINT_PTR height;

			ViewData();
		};

		ViewData viewData;					//表示用データ
		UINT_PTR premium;					//プレミアム種別
		BOOL anonymity;						//匿名フラグ
		UINT_PTR no;						//コメ番
		UINT_PTR vpos;						//コメント表示位置
		time_t date;						//時間
		cuntry::LOCALE locale;				//国コード
		ListenerData *listenerData;			//ユーザ情報
		CNLiteString name;					//名前。ついてこない時もある
		CNLiteString chatBuf;				//チャット本文
		std::vector<CNLiteString> mail;		//メールコマンド
		ULONG_PTR thread;					//スレッド番号
		
	public:


		///
		///nlibのチャットデータをセット
		///
		VOID SetChat(NicoLiveChat &chat_in,ListenerData &listener);

	};




	///
	///コメントリストクラス
	///
	class CCommentList{

	private:
		typedef std::list<CChatData> ChatList;
	public:
		typedef ChatList::iterator iterator;
		typedef ChatList::reference reference;
		typedef ChatList::reverse_iterator reverse_iterator;
	private:
		ChatList chatList;
		iterator shortcut;
	

	
		//エラーコード
	public:
		enum ERRORCORD{
			ERR = -1,
			OK = 0


		};


		//型定義
	

	public:

		///
		///コンストラクタ
		///
		CCommentList();
		
		///
		///デストラクタ
		///
		~CCommentList();
		
		///
		///生放送接続時の処理
		///
		VOID OnConnect();
		

		///
		///破棄時の処理
		///
		VOID OnDestroy();
		
		///
		///格納されたコメント数取得
		///
		UINT_PTR Size();
		

		///
		///選択項目を取得
		///
		iterator GetCurSel();


		INT_PTR GetCurSelNo();

		///
		///選択項目を設定
		///
		VOID SetCurSel(iterator cursel);

		///
		///選択状態のアイテムを取得
		///
		iterator GetCurSelItem();

		///
		///空か判定
		///
		BOOL empty();

		///
		///最初のイテレータを取得
		///
		iterator begin();

		///
		///最後のイテレータを取得
		///
		iterator end();

		///
		///逆向きイテレータの最初を取得
		///
		reverse_iterator rbegein();

		///
		///逆向きイテレータの最後を取得
		///
		reverse_iterator rend();

		///
		///チャット受信時の処理
		///チャットデータの挿入を行う
		///リストが空か、受信したチャットデータのdateの値がリスト最後尾以上のものだった場合最後尾に挿入される
		///そうでなかった場合はリストの最初から引数に渡されたチャットデータのdateより大きいdateを持つデータを探し、そのデータの直前に挿入する
		///
		iterator OnChatReceve(NicoLiveChat_P chatData,LPCTSTR communityID, UINT_PTR count,CCommentListWindow &listWindow);

		///
		///指定した番号のコメント参照を取得
		///
		reference GetChatAt(UINT_PTR no);
		

		///
		///リスト最後の参照を取得
		///
		reference back();

		///
		///ショートカットイテレータを取得
		///
		iterator GetShortCut();
		
		///
		///ショートカットを設定
		///
		BOOL SetShortCut(UINT_PTR no);

		
		
	};


	///
	///ユーザ設定ファイル読取クラス
	///
	class ReadUserSettingXML:public CXmlParser{

	private:
		ListenerData listenerBuff;
		CListenerList &m_listenerList;
		BOOL userNodeFlag;
		
		
		


	public:

		ReadUserSettingXML(CListenerList &in_listenerList);

		void OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs);

		void OnEndElement (const XML_Char *pszName);

		void OnCharacterData (const XML_Char *pszData, int nLength);
	};
	
}