#pragma once

#include "WatchThreadGroup.hpp"
#include "LockManager.hpp"

#include <string>
#include <vector>

#include <assert.h>


class ResourceAccessor
{
public:
	virtual ~ResourceAccessor() {};
	virtual HINSTANCE getInstanceHandle() const = 0;
	virtual LPCTSTR getApplicationName() const;
	virtual HWND getMainHWnd() const;

	int LoadString(UINT uMessageID, LPTSTR buffer, int nBufferMax) const;
	int LoadInteger(UINT uMessageID) const;

	tstring LoadString(UINT uMessageID) const;
	tstring LoadStringFormat(UINT uMessageID, ...) const;
	tstring LoadStringFormatV(UINT uMessageID, va_list marker) const;

	int showMessageBox(UINT uType, LPCTSTR caption, UINT uMessageID, ...) const;
	int showMessageBox(HWND hWnd, UINT uType, LPCTSTR caption, UINT uMessageID, ...) const;
};


class Configuration
{
private:
	
	bool nameMatcherIgnoreCase_;

	bool deleteLog_;

	bool rotateLog_;

	long logCloseSpan_;

	tstring impersonatePasswordEncryption_;

	bool currentDirSetToWatchDir_;


public:
	Configuration();

	virtual ~Configuration() = 0 {};

	bool IsNameMatcherIgnoreCase() const;

	bool IsDeleteLog() const;

	bool IsRotateLog() const;

	long GetLogCloseSpan() const;

	tstring GetImpersonatePasswordEncryption() const;

	bool IsCurrentDirSetToWatchDir() const;

	tstring GetString(LPCTSTR appName, LPCTSTR name, LPCTSTR defValue) const;

	long GetLong(LPCTSTR appName, LPCTSTR name, int defValue) const;

	virtual const tstring& getIniPath() const = 0;

	void initCache();

};

class VersionInfoProvider
{
private:
	tstring fileVersion_;		// ファイルバージョン

	tstring legalCopyright_;	// コピーライト

	tstring versionComment_;	// コメント

public:

	VersionInfoProvider();

	const tstring& getFileVersion() const;

	const tstring& getLegalCopyright() const;

	const tstring& getVersionComment() const;
};


class FWatchApp
	: public ResourceAccessor
	, public Configuration
	, public LockManager
	, public VersionInfoProvider
{
private:
	FWatchApp(const FWatchApp&); //<! 実装なし
	FWatchApp& operator=(const FWatchApp&); //<! 実装なし

	void initDefaultPath();

public:
	FWatchApp();
	virtual ~FWatchApp();
	
	int run(HINSTANCE v_hInstance, LPCTSTR v_lpCmdLine);

	virtual HINSTANCE getInstanceHandle() const;
	virtual LPCTSTR getApplicationName() const;
	virtual HWND getMainHWnd() const;

	virtual const tstring& getInfPath() const;
	virtual const tstring& getInfDir() const;
	virtual const tstring& getIniPath() const;
	virtual const tstring& getIniDir() const;

	void setAppConfVariablesTo(PropertyStringExpander& varExpander, bool useInfDir = true);
	void showHelp(HWND hWnd) const;
	void showContextHelp(HWND hWnd, UINT helpid, POINT pt) const;

	CWatchThreadGroup& getCL();

private:
	HINSTANCE hInstance_;
	HWND hMainWnd_;

	tstring applicationName_;

	tstring helpFile_;		// ヘルプファイルのパス
	tstring iniPath_;		// INIファイルへのパス
	tstring iniDir_;		// INIファイルのディレクトリ
	tstring infPath_;		// LSTファイルへのパス
	tstring infDir_;		// LSTファイルへディレクトリ
	tstring userDataDir_;	// ユーザデータディレクトリ
	tstring moduleDir_;		// 実行ファイルディレクトリ

	CWatchThreadGroup cl_;
};


/*!
 * グローバルなアプリケーションインスタンス
 */
extern FWatchApp app;
