#pragma once

#include "SettingInfo.hpp"
#include "SettingInfoFactory.hpp"

#include <string>


/*!
 * フォルダ選択ダイアログ
 */
class CBrowseFolder
{
private:

	/*!
	 * 親ウィンドウ
	 */
	HWND hParent_;

	/*!
	 * キャプション
	 */
	tstring caption_;

	/*!
	 * 初期ディレクトり、および選択結果ディレクトリ
	 */
	tstring current_;

public:
	CBrowseFolder(HWND hParent, const tstring& caption);

	void SetCurrent(const tstring& current);

	const tstring& GetCurrent() const;

	/*!
	 * フォルダ選択ダイアログを表示し、フォルダが選択された場合、
	 * trueを返します。falseの場合はキャンセルされた場合です。
	 * \param pMalloc フォルダパスを変換するためにシェルのアロケータを使用するため必要となります。
	 * \return フォルダが選択された場合はtrue
	 */
	bool BrowseFolder(IMalloc* pMalloc);

private:

	/*!
	 * コールバック
	 */
	static int CALLBACK CallbackProc(HWND hwnd, UINT uMsg, LPARAM, LPARAM lpData);
};


/*!
 * ウィンドウ操作用ヘルパ
 */
class WindowUtility
{
public:
	virtual ~WindowUtility() {}

	/*!
	 * ウィンドウハンドルを指定してテキストを取得する.
	 * \param ハンドル
	 * \return テキスト
	 */
	tstring getWindowText(HWND v_hWnd) const throw();

	/*!
	 * ウィンドウハンドルを指定してテキストを設定する.
	 * \param v_hWnd ウィンドウハンドル
	 * \param v_text テキスト
	 */
	void setWindowText(HWND v_hWnd, const tstring& v_text) const throw();
};


/*!
 * 監視パラメータの設定用ダイアログ
 */
class CSettingDlg : protected CSettingInfoFactory::ErrorInfoListener, protected WindowUtility
{
private:

	/*!
	 * ファクトリからのエラー通知があったか？
	 * \param エラーが発生している場合はtrue
	 */
	inline bool isErrorOccured() const
	{
		return errorOccured_;
	}

	/*!
	 * エラーをクリアします。
	 */
	void clearError()
	{
		errorOccured_ = false;
	}

	/*!
	 * 元パラメータ
	 */
	CSettingInfo settingInfo_;

	/*!
	 * ファクトリ
	 */
	CSettingInfoFactory factory_;

	/*!
	 * ファクトリからエラーが通知されたか示すフラグ
	 */
	bool errorOccured_;

	/*!
	 * このダイアログのウィンドウハンドル。
	 * これはダイアログプロシージャによって初期化イベントの前に設定されます。
	 */
	HWND hDlg_;

	/* 以下はOnInitDialogで設定される子コントロール */

	HWND hDir;
	HWND hName;
	HWND hVerb;
	HWND hApp;
	HWND hParam;
	HWND hShowWindow;
	HWND hWaitWrite;
	HWND hTolerance;
	HWND hDeletePending;
	HWND hLog;
	HWND hMaxProcess;

	HWND hMaxDepth;
	HWND hDirNotificationAPIRetrySpan;
	HWND hDirNotificationAPIExpirySpan;
	HWND hForceInterval;

	HWND hLogLevel;
	HWND hAppCurrentDir;
	HWND hPersist;

	HWND hArchiveOnly;
	HWND hWatchDelay;
	HWND hNotifyOnStart;

	HWND hIgnoreDuplicate;

	HWND hImpersonate;
	HWND hImpersonateUser;
	HWND hImpersonateDomain;
	HWND hImpersonatePassword;

	HWND hWatchDisabled;

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

public:
	/*!
	 * 元となる正しい監視パラメータを指定して構築します。
	 * \param v_settingInfo 監視パラメータ
	 */
	CSettingDlg( const CSettingInfo& v_settingInfo );

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

	/*!
	 * ダイアログを表示します。
	 * \return 正しく入力された場合はtrue
	 */
	bool show(HWND hWnd );

	/*!
	 * パラメータを構築します。
	 * このメソッドはshowメソッドが正しく終了してない場合は呼び出してはなりません。
	 * \param パラメータ
	 */
	CSettingInfo createSettingInfo() const;

protected:

	/*!
	 * ファクトリからパラメータの設定に過ちがあるたびにエラーが通知されます。
	 * 戻り値としてfalseを指定するとパラメータは設定されません。
	 * trueを指定すると、回復できる場合は回復させてパラメータを設定させます。
	 * ただし、パラメータの回復ができない場合はfalseと同じです。
	 * \param v_errorInfo エラー情報
	 * \return 回復させる場合はtrueを指定します。
	 */
	virtual bool notifyErrorInfo( const tstring& v_errorInfo ) throw();

private:

	/*!
	 * 元となるパラメータをダイアログのコントロールに配置します。
	 */
	void setInitialParam();

	/*!
	 * ダイアログが初期化されたときに呼び出されるハンドラ。
	 */
	void OnInitDialog();

	/*!
	 * コマンドハンドラ
	 */
	BOOL onCommand( UINT btn );

	/*!
	 * OKボタンのハンドラ。
	 * ダイアログの入力項目が正当である場合のみダイアログを終了させます。
	 */
	void onOK();

	/*!
	 * CANCELボタンのハンドラ。
	 * ダイアログの入力をキャンセル終了させます。
	 */
	void onCancel();

	/*!
	 * 監視フォルダ選択ハンドラ
	 */
	void onBrowseDir();

	/*!
	 * アプリケーション選択ハンドラ
	 */
	void onOpen();

	/*!
	 * ログ出力先選択ハンドラ
	 */
	void onLogSelect();

	/*!
	 * カレントディレクトリ選択ハンドラ
	 */
	void onBrowseCurDir();

	/*!
	 * 永続化ファイル選択ハンドラ
	 */
	void onSelPersist();

private:

	/*!
	 * ダイアログプロシージャ
	 */
	static LRESULT CALLBACK DlgProc(HWND,UINT,WPARAM,LPARAM);

	/*!
	 * ワードラッププロシージャ
	 */
	static int __stdcall NoWordwrapProc(LPTSTR lpch, int ichCurrent, int cch, int code);
};
