#pragma once

#include <string>

/*!
 * ウィンドウ表示サイズ
 */
class ShowWindowType
{
private:
	/*!
	 * プライベートコンストラクタ
	 * \param ID
	 */
	ShowWindowType(const int v_showWindowType);

public:

	/*!
	 * デフォルト値を設定するデフォルトコンストラクタ
	 */
	ShowWindowType();

	/*!
	 * コピーコンストラクタ
	 * \param コピー元
	 */
	ShowWindowType(const ShowWindowType& v_other);

	/*!
	 * コピー
	 * \param コピー元
	 */
	ShowWindowType& operator=(const ShowWindowType& v_other);

	/*!
	 * とりうる値の一覧
	 */
	enum member
	{
		MINIMIZED_NOACTIVE = 0,
		NORMAL = 1,
		MAXIMIZED = 2,
		HIDDEN = 3,
		MINIMIZED = 4
	};

	/*!
	 * int型への変換はIDを返します。
	 * \return ID
	 */
	operator int() const;

	/*!
	 * 説明を取得します。
	 * \return 説明
	 */
	tstring getDescription() const;

	/*!
	 * ウィンドウを開くコマンドを返します。
	 * これはSW_SHOWNORMALなどの定数です。
	 * \param コマンドID
	 */
	int getShowCommand() const;

	/*!
	 * IDを指定して取得します。
	 * 範囲外の場合はデフォルトを返します。
	 */
	static ShowWindowType valueOf(const int v_showWindowType);

	/*!
	 * 等しいか検証します。
	 * \param 比較対象
	 * \return 等しければtrue
	 */
	inline bool operator==(const ShowWindowType& v_other) const
	{
		return v_other.showWindowType_ == showWindowType_;
	}

	/*!
	 * 等しくないか検証します。
	 * \param 比較対象
	 * \return 等しくなければtrue
	 */
	inline bool operator!=(const ShowWindowType& v_other) const
	{
		return v_other.showWindowType_ != showWindowType_;
	}

private:

	int showWindowType_;

};

/*!
 * 監視設定
 */
class CSettingInfo
{
	/**
	 * 書き込みアクセスできるのはファクトリだけ。
	 * ファクトリは必ず正しい状態のオブジェクトを返す。
	 */
	friend class CSettingInfoFactory;

protected:

	tstring watchDir_;
	tstring watchFile_;
	tstring action_;
	tstring appName_;
	tstring param_;
	tstring log_;

	ShowWindowType showWindow_;

	int nWaitWrite_;
	int nTolerance_;
	
	unsigned int nMaxProcess_;

	int nDeletePending_;

	// 追加

	int nMaxDepth_;
	int nForceInterval_;
	int nDirNotificationAPIRetryInterval_;
	int nDirNotificationAPIExpirySpan_;

	bool bUsingNotificationAPI_;

	int logLevel_;
	tstring appCurrentDir_;
	tstring persist_;

	bool archiveOnly_;
	bool notifyOnStart_;
	int nWatchDelay_;

	bool ignoreDuplicate_;

	bool impersonate_;
	tstring impersonateUser_;
	tstring impersonateDomain_;
	tstring impersonatePassword_;

	bool watchDisabled_;

public:

	/*!
	 * 有効なデフォルト値で初期化されたオブジェクトを構築します。
	 */
	CSettingInfo();

	/*!
	 * コピーコンストラクタ
	 * \param v_other コピー元
	 */
	CSettingInfo(const CSettingInfo& v_other);

	/*!
	 * コピー
	 * \param v_other コピー
	 */
	CSettingInfo& operator=(const CSettingInfo& v_other);

	/*!
	 * デストラクタ
	 */
	virtual ~CSettingInfo();

	/*!
	 * 同値であるか判定します。
	 * \param 比較対象
	 * \return 同一であればtrue、そうでなければfalse
	 */
	bool operator==(const CSettingInfo& v_other) const;

	/*!
	 * 同値でないかか判定します。
	 * \param 比較対象
	 * \return 同一であればfalse、そうでなければtrue
	 */
	bool operator!=(const CSettingInfo& v_other) const;

	/*!
	 * 監視ディレクトリを取得します。
	 * \return 監視ディレクトリへのパス
	 */
	inline const tstring& getWatchDir() const {
		return watchDir_;
	}

	/*!
	 * 監視ファイルを取得します。
	 * \return 監視ファイルのパターン
	 */
	inline const tstring& getWatchFile() const {
		return watchFile_;
	}

	/*!
	 * アクションを取得します。
	 * \return アクション
	 */
	inline const tstring& getAction() const {
		return action_;
	}

	/*!
	 * アクションを実行するプログラム名を取得します。
	 * \return プログラム名
	 */
	inline const tstring& getAppName() const {
		return appName_;
	}

	/*!
	 * アクションを実行するプログラムに引き渡すパラメータを取得します。
	 * \return パラメータ
	 */
	inline const tstring& getParam() const {
		return param_;
	}

	/*!
	 * ログの書き込み先パスを取得します。
	 * \return ログの書き込み先
	 */
	inline const tstring& getLog() const {
		return log_;
	}

	/*!
	 * ログの書き込みが指定されているか取得します。
	 * \return ログの書き込みが指定されている場合はtrue
	 */
	inline bool isEnableLogging() const {
		return ! log_.empty();
	}

	/*!
	 * 監視対象ファイルの書き込み完了待機までの時間を取得します。
	 * \return 書き込み完了待機時間
	 */
	inline int getWaitWrite() const {
		return nWaitWrite_;
	}

	/*!
	 * プロセスの終了待ちの有無を取得します。
	 * \return プロセスが終了するまで次のプロセスを起動しない場合はtrue
	 */
	inline unsigned int getMaxProcess() const {
		return nMaxProcess_;
	}

	/*!
	 * プロセスを起動したときのウィンドウサイズ
	 * \return ウィンドウサイズ
	 */
	inline ShowWindowType getShowWindow() const {
		return showWindow_;
	}

	/*!
	 * ファイルが同一であるとみなす範囲(精度)を取得します。
	 * \return 精度(mSec)
	 */
	inline int getTolerance() const {
		return nTolerance_;
	}

	/*!
	 * ファイル削除を検知してからエントリを削除する時間(100mSec単位)を取得します。
	 * \return エントリが削除されるまでの期間(100mSec)
	 */
	inline int getDeletePending() const {
		return nDeletePending_;
	}

	/*!
	 * サブディレクトリを操作する最大の深さを取得します。
	 * 0で指定したディレクトリのみを対象とします。
	 * \return 最大の深さ、0以上
	 */
	inline int getMaxDepth() const {
		return nMaxDepth_;
	}

	/*!
	 * 強制検査の間隔(秒)を取得します。
	 * 0の場合は強制走査しません。
	 * 0の場合はディレクトリ操作APIが有効でなければなりません。
	 * \return 強制間隔の秒数
	 */
	inline int getForceInterval() const {
		return nForceInterval_;
	}

	/*!
	 * ディレクトリ監視APIによる監視を使うか取得します。
	 * 使う無い場合は強制捜査の間隔を1以上にしなければなりません。
	 * \return ディレクトリ監視APIを使う場合はtrue
	 */
	inline bool isUsingDirNotificationAPI() const {
		return bUsingNotificationAPI_;
	}

	/*!
	 * ディレクトリ監視APIの構築に失敗した場合の再試行間隔(秒)。
	 * 0の場合は即時試行します。
	 * \return 再試行の間隔(秒)
	 */
	inline int getDirNotificationAPIRetryInterval() const {
		return nDirNotificationAPIRetryInterval_;
	}

	/*!
	 * ディレリトクリ監査APIの有効期限(秒)を取得します。
	 * 指定した期限を経過すると、ディレクトリ監査APIは再作成されます。
	 * 0を指定した場合は再作成しません。
	 * ディレクトリ監査APIを使わない場合は意味を持ちません。
	 * \return 有効期限(秒)
	 */
	inline int getDirNotificationAPIExpirySpan() const {
		return nDirNotificationAPIExpirySpan_;
	}

	/*!
	 * ログ出力時の詳細度を取得します。
	 * 値が大きいほど詳細となります。
	 */
	inline int getLogLevel() const {
		return logLevel_;
	}

	/*!
	 * アプリケーション実行時のカレントディレクトリ。
	 * 空の場合はFWatch.iniの設定により、監視フォルダまたはデフォルト(FWatchのディレクトリ)となる。
	 */
	inline const tstring& getAppCurrentDir() const {
		return appCurrentDir_;
	}

	/*!
	 * 永続化ファイルを取得します。
	 * 指定されていない場合は永続化しません。
	 */
	inline const tstring& getPersist() const {
		return persist_;
	}

	/*!
	 * アーカイブ属性のファイルのみ通知します。
	 */
	inline const bool isArchiveOnly() const {
		return archiveOnly_;
	}

	/*!
	 * 開始時点で存在するファイルも通知します。
	 */
	inline const bool isNotifyOnStart() const {
		return notifyOnStart_;
	}

	/*!
	 * 連続する通知を一つにまとめる期間(mSec)
	 */
	inline const int getWatchDelay() const {
		return nWatchDelay_;
	}

	/*!
	 * 同一ファイルを同時実行しないか?
	 */
	inline const bool isIgnoreDuplicate() const {
		return ignoreDuplicate_;
	}

	/*!
	 * ユーザを偽装するか?
	 */
	inline const bool isImpersonate() const {
		return impersonate_;
	}

	/*!
	 * 偽装ユーザ名
	 */
	inline const tstring& getImpersonateUser() const {
		return impersonateUser_;
	}

	/*!
	 * 偽装ドメイン
	 */
	inline const tstring& getImpersonateDomain() const {
		return impersonateDomain_;
	}

	/*!
	 * 偽装パスワード
	 */
	inline const tstring& getImpersonatePassword() const {
		return impersonatePassword_;
	}

	/*!
	 * 監視を無効にするか?
	 */
	inline bool isWatchDisabled() const {
		return watchDisabled_;
	}
};
