#if !defined(AFX_INITFORMEX_H__FC223DE1_F108_11D0_A459_004095E1DAEA__INCLUDED_)
#define AFX_INITFORMEX_H__FC223DE1_F108_11D0_A459_004095E1DAEA__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "artbear\Timer.h"
#include "artbear\FilesDropTarget.h"
#include "artbear\ModalWindowTimer.h"
#include "artbear\SystemMessagesHooker.h"

#include <boost/scoped_ptr.hpp>
#include "artbear\istrmap.h"

extern CMDIFrameWnd * pMainWindow;

class CStatusBarManager;
class CAddInApp;

class CInitFormEx : private boost::noncopyable
{
	CInitFormEx(); // запрещаю создавать непосредственно !
public:

	typedef shared_ptr<CInitFormEx> CPtr;

	static CInitFormEx& Get() { if (!singletone) singletone = CPtr(new CInitFormEx);  return *singletone; };
	static DestroySingletone() { singletone.reset(); };

	~CInitFormEx();

	bool Init(void);

	void Apply(void);
	void BeforeApply(void);

	void SetIndicatorsForStatusBar(SECStatusBar* pStatus, unsigned int const * num1, int num2);
	void ShowKeyboardIndicator(BOOL bShow );

	BOOL SetKeyboardSystemHook(int bSetFlag);
	BOOL SetMouseSystemHook(int bSetFlag);

	static bool IsVersionOfPlatformAreWIN32_NT() { return VER_PLATFORM_WIN32_NT == CInitFormEx::Get().m_PlatformId; };
	static bool IsVersionOfPlatformAreEMBEDDEDNT() { return VER_SUITE_EMBEDDEDNT == (VER_SUITE_EMBEDDEDNT & CInitFormEx::Get().m_wSuiteMask); };
	static bool IsVersionOfPlatform(DWORD dwVer) { return dwVer == CInitFormEx::Get().m_PlatformId; };

	void SetSystemTopmostModalState(BOOL bSet);

	bool IsSQLVersion(void) { return m_bIsSqlVersion; };

private:

	void Destroy(void);

	void InitEvents(void);

	void SaveSettingsToRegistry();
	void LoadSettingsFromRegistry();

	void AddSystemHooks();
	void DestroySystemHooks();

	//BOOL SetSystemHook(int HookID, HHOOK& HookHandle, HOOKPROC HookProc, int bSetFlag);
	BOOL SetSystemHook(CSystemMessagesHooker& HookHandle, int HookID, HOOKPROC HookProc, int bSetFlag);

	static LRESULT __stdcall Key_Hook(int code, WPARAM wParam, LPARAM lParam);
	static LRESULT __stdcall Mouse_Hook(int code, WPARAM wParam, LPARAM lParam);
	static LRESULT __stdcall Wnd_Hook(int code, WPARAM wParam, LPARAM lParam);
	static LRESULT __stdcall WndPre_Hook(int nCode, WPARAM wParam, LPARAM lParam);

	LRESULT Key_Hook_Handler(int code, WPARAM wParam, LPARAM lParam);
	LRESULT Mouse_Hook_Handler(int code, WPARAM wParam, LPARAM lParam);
	LRESULT Wnd_Hook_Handler(int code, WPARAM wParam, LPARAM lParam);
	LRESULT WndPre_Hook_Handler(int nCode, WPARAM wParam, LPARAM lParam);

	void SendMouseEvent(WPARAM wParam, CGetDoc7* pDoc7, CValue **ppParams);
	static CGetDoc7* GetActiveDocIntoMouseEvent(HWND hwnd, const POINT& pt);

	bool HandleMouseEventAndReturnFSO(WPARAM wParam, LPARAM lParam);

	bool HandleKeyEventAndReturnFSO(WPARAM wParam, LPARAM lParam);

	void SetupPlatformID();

	void GetNamesOfAllForms();
public:

	CTimerWithEvent::PCTimerWithEvent m_GlobalTimer;

	CModalWindowTimers& GetModalWindowTimers() { return m_ModalWindowTimers; }

	bool m_bStopHook_Keyboard_Mouse; // TODO неоднозначность использования в различных хуках !!

	sh_ptr<CStatusBarManager> pStatusBarManager;

	UINT m_uiCenterBrowse;

private:
	CFilesAndURLDropTarget  m_FilesDropTarget;
	CModalWindowTimers m_ModalWindowTimers;

	static CPtr singletone;

	CSystemMessagesHooker m_KeyboardHookHandle;//HHOOK m_KeyboardHookHandle;
	CSystemMessagesHooker m_MouseHookHandle;//HHOOK m_MouseHookHandle;
	CSystemMessagesHooker m_WndHookHandle;//HHOOK m_WndHookHandle;
	CSystemMessagesHooker m_WndPreHookHandle;//HHOOK m_WndPreHookHandle;

	DWORD m_PlatformId;
	WORD m_wSuiteMask;
	BOOL m_bModalState;

	bool m_bIsSqlVersion; // кеширование
};

enum ModuleEvents
{
    meOnChar,
    meOnCharUp,

    meOnItemExpanding,
    meOnItemExpanded,
    meOnItemCollapsing,
    meOnItemCollapsed,
	meOnCheckItem,
    meOnRButtonOverTree,
    meOnLButtonOverTree,

	meOnStartObjectLock,
    meOnObjectLocked,
    meOnPrintTable,
    //meOnPostPrint,
    //meOnPrePrint,

	meOnLoadForm,
    meOnLoadFormModule,
    meOnLoadAsExternalForm,
    meOnLoadAsExternalDialog,

	meOnReadRepHistory,
	meOnWriteRepHistory,
	meOnActivateWindow,
	meOnDeactivateWindow,
	meOnClosed,
	meOnActivate,

	meOnRefresh,

	meOnMultiLinePic,
	meOnCreateForm,
	meOnSize,
	meOnWndCommand,

	meOnMouseMove,
	meOnRButtonDown,
	meOnRButtonUp,
	meOnRButtonDblClk,
	meOnLButtonDown,
	meOnLButtonUp,
	meOnLButtonDblClk,
	meOnMButtonDown,
	meOnMButtonUp,
	meOnMButtonDblClk,
	meOnMouseWheel,

	meOnLocalTimerForm,
	meOnGlobalTimerForm,

	meOnStartSystem,
	meOnFinishSystem,
	meOnDeleteItem,
	meOnOpenHistory,
	meOnWriteHistory,
	meOnDeleteHistory,
	meOnWriteConst,
	meOnDeleteDoc,
	meOnChangeTimeDoc,
	meOnUnPosting,
	meOnSetSelectInJournal,
	meOnDeleteAccount,
	meOnOperEntryOffOn,
	meOnPeriodChange,
	meOnSheetCellProcessing,

	meOnExternEventProcessing,

	meOnDrop,
	meOnURLDrop,

	meOnActivateDocForm,
	meOnCommand,
	meOnSysCommand,

	meOnLDblClkStatusBar,
//	meTestCommandEnable,
//	meOnInitMenu,

	meOnTestAccess,
	meOnWriteMessage,
	meOnShowControlBar,
	meOnWriteStatusLine,

	meOnOpen,
	meOnClose,
	meOnNewLine,
	meOnWrite,
	meOnMoveIntoOtherGroup,
	meOnCalculating,
	meOnStartValueChoice,
	meOnReopen,
	meOnTabCtrlPosChanged,
	meProcessValueChoice,
	meOnSelectLine,
	meProcessSelectLine,
	meNew,
	meInputNew,
	meInputCausedBy,
	meOnEditNewLine,
	meOnStartEditLine,
	meOnFinishLineEdit,
	meOnChangeLinesOrder,
	meOnDeleteLine,
	meOnSetOwner,
	meOnSetParent,
	meOnHierarchyChange,
	meOnSetViewBound,
	meOnSetSelection,
	meOnSetPresentation,
	meOnSetSelect,
	meOnResultUpdate,
	meOnUpdateCancel,
	meOnSetRange,

	meOnSaveSheetDoc,

	meTraceLog,
	meOnValueTraceLogPresent,

    meLastEvent
};

class CIconManager
{
	HICON hBigIcon;
	HICON hSmallIcon;
	WNDPROC hWndProc;

	static CMapPtrToPtr mapSetIcon;
public:
	CIconManager(HWND hWnd);

	static void Add(HWND hWnd, HICON hNewIcon);
	static void DestroyStaticContainer();
private:
	Set(HICON hNewIcon);

	static LRESULT CALLBACK WndProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam);
};

extern BOOL m_bEnabledColor;
extern BOOL m_bLocalColor;
extern BOOL m_bShowKL;
//extern class CApp7* pApp;
//extern class CBkEndUI * pBkEndUI;

CView* GetFormView(CDocument* pDoc);

struct SStatusBarPane
{
	public:
		UINT ID;
		int Width;
		int Style;
		BOOL Visible;
		BOOL System;
		CString Caption;
		CString Name;
		BOOL Stretch;
		int ImageIndex;

		static SStatusBarPane* Create() { return new SStatusBarPane; };

		SStatusBarPane()
		{
			ID = 0L;
			Width = 0;
			Style = 0;
			Visible = FALSE;
			System = FALSE;
			Caption = "";
			Name = "";
			Stretch = FALSE;
			ImageIndex = -1;
		};

		void SetPane(UINT uiID, CString csCaption, CString csName, int iWidth, int iStyle, int iImageIndex, BOOL bVisible, BOOL bSystem)
		{
			ID = uiID;
			Width = iWidth;
			Style = iStyle;
			Visible = bVisible;
			System = bSystem;
			Caption = csCaption;
			Name = csName;
			ImageIndex = iImageIndex;

			if(iStyle&SBPS_STRETCH)
				Stretch = TRUE;
			else
				Stretch = FALSE;

			if(bSystem)
			{
				ImageIndex = -1;
				switch (uiID)
				{
					case 0x0000:
						Name = "СтрокаСостояния";
						break;
					case 0xE701:
						Name = "CapsLock";
						break;
					case 0xE702:
						Name = "NumLock";
						break;
					case 0xE712:
						Name = "ТочкаАктуальности";
						break;
					case 0xE715:
						Name = "БухгалтерскиеИтоги";
						break;
					case 0xE71B:
						Name = "ТекущийПериодРасчета";
						break;
				}
			}
			else if(ImageIndex >= 0)
			{
				Style |= SBPS_OWNERDRAW;
			}

		};
};

// класс для перехвата виртуальных функций
class SECStatusBarFormEx: public SECStatusBar
{
public:
	virtual void  DrawItem(struct tagDRAWITEMSTRUCT *);	//367
};

class CStatusBarManager
{

public:
	CStatusBarManager() : m_StatusTimer(0)
	{
		m_pStatus = GetAppStatusBar();
		// подменяем таблицу виртуальных функций статус бара
		SECStatusBarFormEx * pTempSB = new SECStatusBarFormEx;
		adrOriginalVT = ((DWORD*) m_pStatus)[0];
		adrWrapVT = ((DWORD*)pTempSB)[0];

		((DWORD*) m_pStatus)[0] = ((DWORD*)pTempSB)[0];

		delete pTempSB;

		m_ImageList.Create(16, 15, ILC_COLOR32|ILC_MASK, 2, 0);
		//m_ImageList.Create(16, 16, ILC_COLOR32|ILC_MASK, 4, 0);

	};

	~CStatusBarManager()
	{
		if(m_pStatus)
			if(m_StatusTimer)
			{
				m_pStatus->KillTimer(m_StatusTimer);
			};

		DeleteAllPanes();
		int count = m_Panes.GetSize();
		for(int i = 0; i < count; i++)
		{
			SStatusBarPane* pPane = (SStatusBarPane*)m_Panes.GetAt(i);
			delete pPane;
		};
	};

	static sh_ptr<CStatusBarManager> Create() { return sh_ptr<CStatusBarManager>(new CStatusBarManager); };
	static SECStatusBar* GetAppStatusBar() { return (SECStatusBar*)AfxGetApp()->m_pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR); };

	void Init(BOOL bShow);
	BOOL GetStatusBar();
	UINT AddPane(CString csCaption, CString csName, int iWidth, int iStyle, int iImageIndex, BOOL bVisible);
	void DeletePane(UINT uiPaneID);
	void MovePanel(UINT uiPaneID, int iSteps);
	void DeleteAllPanes();
	void SetPaneText(UINT PaneID, CString Caption);
	void SetPaneWidth(UINT uiPaneID, int uiWidth);
	SStatusBarPane* GetPaneByID(UINT PaneID);
	SStatusBarPane* GetPaneByName(CString csName);
	SStatusBarPane* GetPaneByIndex(int iIndex);
	SStatusBarPane* GetVisiblePaneByIndex(int iIndex);
	int GetPaneIndexByID(UINT uiPaneID);
	int GetPaneCount() {return m_Panes.GetSize();};
	int GetPaneWidth(SStatusBarPane* pPane);
	int GetPaneWidth(UINT uiPaneID);
	void SetStretchPane(SStatusBarPane* pPane);
	int GetPanePosition(SStatusBarPane* pPane);

	//void SetSystemPaneText(int PaneIndex, const char * buf, int count);

	void SetStatusBar();
	void SetIndicators(BOOL bShow, BOOL bHard = FALSE);
	//void UpdateSystemPanes();

	void UpdateElements();

	void AddImagesToList(CBitmap* pbmImage);

	void Invalidate();

	CImageList m_ImageList;
	DWORD adrOriginalVT;
	DWORD adrWrapVT;

private:

	SStatusBarPane* AddPane(UINT uiPaneID, CString csCaption, CString csName, int iWidth, int iStyle, int iImageIndex, BOOL bVisible, BOOL bSystem = FALSE);
	void SetTimer();

	static void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime);
	static void SetKeyboardLayout(SECStatusBar* pStatus);
	static void SetLocalTime(SECStatusBar* pStatus);

	UINT m_StatusTimer;
	SECStatusBar* m_pStatus;
	CPtrArray m_Panes;
};

class CAllFormsNamesManager : boost::noncopyable
{
public:
	static CAllFormsNamesManager* Get() 
		{
			if (!pAllFormsNamesManager){
				pAllFormsNamesManager = boost::shared_ptr<CAllFormsNamesManager>(new CAllFormsNamesManager);
				pAllFormsNamesManager->GetNamesOfAllForms();
			}
			return pAllFormsNamesManager.get();
		}
	static Destroy() { pAllFormsNamesManager.reset(); }

	~CAllFormsNamesManager()
	{
		DocNamesArray.ForEachValue(val_deleter());
	}
	void Add(LPCTSTR pKey, DWORD id, LPCTSTR pName)
		{
			SDocNames *pDocNames = new SDocNames(id, pName); // TODO проверить удаление
			DocNamesArray.SetAt(pKey, pDocNames);

		}
	bool Lookup(LPCTSTR pName, long* pID, LPCTSTR * pFolder)
		{
			SDocNames *pDocNames = NULL;
			if(DocNamesArray.Lookup(pName, pDocNames))
			{
				*pID = pDocNames->id;
				*pFolder = pDocNames->strFolder;
				return true;
			}
			return false;
		}
	
	template<typename UnaryOp>
	void ForEach(UnaryOp op)
	{
		POSITION pos = DocNamesArray.GetStartPosition();
		while(pos)
		{
			CString key;
			SDocNames* ptr;
			DocNamesArray.GetNextAssoc(pos, key, ptr);
			//pCont->m_pBodyTextDoc->AddLine(key);
			op(key);
		}
	}

private:
	//CAllFormsNamesManager() {}
	void GetNamesOfAllForms();

	static boost::shared_ptr<CAllFormsNamesManager> pAllFormsNamesManager;

	struct SDocNames{
		DWORD id;
		CString strFolder;

		SDocNames(DWORD id1, LPCTSTR pName) : id(id1), strFolder(pName)  {};
	};

	CIStringMap<SDocNames*, SDocNames*> DocNamesArray;

	static int procGetAllTypedItem(class CString &str,long l1,long l2,enum PageType pt);

	struct val_deleter{ void operator()(SDocNames* pVal){ delete pVal;} };
};

#endif AFX_INITFORMEX_H__FC223DE1_F108_11D0_A459_004095E1DAEA__INCLUDED_
