#pragma once

#include "WatchThread.hpp"
#include "SettingInfo.hpp"

#include <string>
#include <vector>

class CWatchThreadGroup
{
private:
	/*!
	 * ドライランモード
	 */
	const bool dryrun_;

	/*!
	 * 変更フラグ
	 */
	mutable bool modified_;

	/*!
	 * 監視スレッドのリスト
	 */
	typedef std::vector<CWatchThread*> CWatchThreadList;
	CWatchThreadList watchList_;

private:
	CWatchThreadGroup(const CWatchThreadGroup&); //<! 実装なし
	CWatchThreadGroup& operator=(const CWatchThreadGroup&); //<! 実装なし

public:
	
	/*!
	 * 監視スレッドグループを構築します。
	 * ドライランモードを有効にするとスレッドは実際には作成されず編集のみとなります。
	 * \param v_dryrun ドライランモードの場合、true
	 */
	CWatchThreadGroup(const bool v_dryrun);

	/*!
	 * 監視グループを解放します。
	 * すべてのスレッドは停止され解放されます。
	 */
	virtual ~CWatchThreadGroup();

	/*!
	 * 全てのスレッドを解放し、サイズ0にします。
	 */
	void ReleaseAllThreads();

	/*!
	 * 監視スレッド数を取得します。
	 * 現在停止中のものも含まれます。
	 * \return 監視スレッド数
	 */
	unsigned int size() const;

	/*!
	 * 監視スレッドの監視設定を取得します。
	 * \param 監視スレッドのインデックス
	 * \return 監視スレッドの監視設定
	 */
	const CSettingInfo& getInfo(unsigned int idx) const;

	/*!
	 * 新しい監視スレッドを作成しグループに登録します。
	 * 登録したスレッドのポインタを返します。
	 * 監視スレッドのポインタは管理済みのため呼び出し側がdeleteする必要はありません。
	 * \param 監視スレッドのインデックス
	 * \param v_settingInfo 監視設定
	 * \return 監視スレッドのポインタ。
	 */
	CWatchThread *append(const CSettingInfo& v_settingInfo);

	/*!
	 * 監視スレッドを更新します。
	 * 設定に変更がない場合はスレッドはそのままです。
	 * 変更されている場合はスレッドは再作成されます。
	 * 再作成されたか、もしくは既存の監視スレッドのポインタが返されます。
	 * 監視スレッドのポインタは管理済みのため呼び出し側がdeleteする必要はありません。
	 * \param 監視スレッドのインデックス
	 * \param v_settingInfo 監視設定
	 * \return 監視スレッドのポインタ。
	 */
	CWatchThread *replace(unsigned int idx, const CSettingInfo& v_settingInfo);

	/*!
	 * 監視スレッドを破棄します。
	 * \param 監視スレッドのインデックス
	 * \return 破棄された場合はtrue、そうでない場合はfalse
	 */
	bool erase(unsigned int idx);


	/*!
	 * 無効ではない、すべてのスレッドを開始します。
	 * すでに開始済みのものは何もしません。
	 */
	void startAll();

	/*!
	 * 指定したスレッドを開始します。
	 * 既に開始済みであれば何もしません。
	 * スレッドがの監視がディセーブル指定であっても開始されます。
	 * \return すでに開始されているか開始された場合はtrue、開始できなかった場合はfalse
	 */
	bool start(unsigned int idx);

	/*!
	 * 指定したスレッドを停止します。
	 * すでに停止済みであれば何もしません。
	 * \return スレッドが既に停止済みであるか停止された場合はtrue、定時的無かった場合はfalse
	 */
	bool stop(unsigned int idx);

	/*!
	 * スレッドが動作中であるか判定します。
	 * いずれか1つでも動作中であればtrueを返します。
	 * \return いずれかのスレッドが動作中であればtrue
	 */
	bool isRunning() const;

	/*!
	 * 指定したスレッドが動作中であるか判定します。
	 * \param 監視スレッドのインデックス
	 * \return スレッドが動作中であればtrue
	 */
	bool isRunning(unsigned int idx) const;


	/*!
	 * ドライランモードであるか?
	 * \return ドライランモードであればtrue
	 */
	bool isDryrRun() const;


	/*!
	 * 設定ファイルから監視設定を読み取りスレッドグループを構築します。
	 * \param InfPath 監視リストファイル
	 * \return 正常に読み込めた場合はtrue、そうでない場合はfalse
	 */
	bool LoadInfData(const tstring& InfPath);

	/*!
	 * 現在の監視設定を設定ファイルに書き込みます。
	 * \param InfPath 監視リストファイル
	 * \return 正常に書き込めた場合はtrue、そうでない場合はfalse
	 */
	bool SaveInfData(const tstring& InfPath, bool bForce = false) const;

	/*!
	 * 初期化時点、もしくはLoadInfData呼び出し後に、なんらかの設定変更があるか?
	 * \return 設定変更があればtrue
	 */
	bool isModified() const;

protected:

	/*!
	 * スレッドの開始にあたってログの初期化処理を行います。
	 * ただし、同一ログファィルをもつスレッドが開始済みであれば、
	 * すでに初期化済みとみなし、初期化処理はスキップされます。
	 * \param settingInfo 監視設定
	 */
	void ClearLog(const CSettingInfo& settingInfo) const;
};
