#include <common/hookproc.hpp>
#include <common/dde.hpp>
#include <common/mmsystem.hpp>

WinHookProc::WinHookProc(HookType hookType)
: mPrevHook(0), mhHookWnd(0), mHookType(hookType)
{
}

WinHookProc::~WinHookProc()
{
  unhookWin();
}

BOOL WinHookProc::hookWin(HWND hWnd)
{
	unhookWin();
	windowHandle(hWnd);
	if(!windowHandle())return FALSE;
	::SetProp(windowHandle(),(LPSTR)"INSTANCEDATA@@NEARPTR",(HANDLE)((void*)this));
	prevHook((WNDPROC)::SetWindowLong(windowHandle(),winID(),(DWORD)hookProc));
	return TRUE;
}

BOOL WinHookProc::unhookWin(void)
{
	if(!isOkay()||!prevHook())return FALSE;
	::SetWindowLong(windowHandle(),winID(),(DWORD)prevHook());
	::RemoveProp(windowHandle(),(LPSTR)"INSTANCEDATA@@NEARPTR");
	prevHook(0);
	windowHandle(0);
	return TRUE;
}

DWORD WinHookProc::winID(void)const
{
	return GWL_WNDPROC;
}

BOOL WinHookProc::isOkay(void)const
{
  return (windowHandle()?TRUE:FALSE);
}

LRESULT CALLBACK WinHookProc::hookProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
	LRESULT callResult;
	WinHookProc *pWinHookProc=(WinHookProc*)::GetProp(hWnd,"INSTANCEDATA@@NEARPTR");
	if(!pWinHookProc)return ::DefWindowProc(hWnd,msg,wParam,lParam);

  if(WinHookProc::HookBefore==pWinHookProc->hookType())
	{
	  CallbackDataHook callbackDataHook(pWinHookProc->windowProcedure(hWnd,msg,wParam,lParam));
	  if(!callbackDataHook.hookReturnCode())callResult=::CallWindowProc(pWinHookProc->mPrevHook,hWnd,msg,wParam,lParam);
 	  else callResult=callbackDataHook.hookReturnCode();
	}
	else
	{
    callResult=::CallWindowProc(pWinHookProc->mPrevHook,hWnd,msg,wParam,lParam);
		pWinHookProc->windowProcedure(hWnd,msg,wParam,lParam);
	}
	if(WM_NCDESTROY==msg)pWinHookProc->unhookWin();
	return callResult;
}

CallbackDataHook WinHookProc::windowProcedure(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
  CallbackDataHook callbackData(wParam,lParam,hWnd);
	switch(message)
	{
		case WM_NCCREATE :
			if(!installedHandlers(VectorHandler::NCCreateHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::NCCreateHandler,callbackData));
			break;
		case WM_CREATE :
			if(!installedHandlers(VectorHandler::CreateHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::CreateHandler,callbackData));
			break;
		case WM_PAINT :
			if(!installedHandlers(VectorHandler::PaintHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::PaintHandler,callbackData));
			break;
		case WM_DRAWITEM :
			if(!installedHandlers(VectorHandler::DrawItemHandler))break;
		  callbackData.hookReturnCode(callHandlers(VectorHandler::DrawItemHandler,callbackData));
			break;
		case WM_TIMER :
			if(!installedHandlers(VectorHandler::TimerHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::TimerHandler,callbackData));
			break;
		case WM_CHAR :
			if(!installedHandlers(VectorHandler::CharHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::CharHandler,callbackData));
			break;
		case WM_COMMAND :
			if(!installedHandlers(VectorHandler::CommandHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::CommandHandler,callbackData));
			break;
		case WM_COMPACTING :
			if(!installedHandlers(VectorHandler::CompactingHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::CompactingHandler,callbackData));
			break;
		case WM_WININICHANGE :
			if(!installedHandlers(VectorHandler::WinIniChangeHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::WinIniChangeHandler,callbackData));
			break;
		case WM_SYSCOLORCHANGE :
			if(!installedHandlers(VectorHandler::SysColorChangeHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::SysColorChangeHandler,callbackData));
		case WM_CTLCOLOR :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLORMSGBOX :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLOREDIT :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLORLISTBOX :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLORBTN :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLORDLG :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLORSCROLLBAR :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_CTLCOLORSTATIC :
			if(!installedHandlers(VectorHandler::ControlColorHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::ControlColorHandler,callbackData));
			break;
		case WM_DDE_INITIATE :
			if(!installedHandlers(VectorHandler::DDEInitiateHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DDEInitiateHandler,callbackData));
			break;
		case WM_DDE_ACK :
			if(!installedHandlers(VectorHandler::DDEAckHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DDEAckHandler,callbackData));
			break;
		case WM_DDE_REQUEST :
			if(!installedHandlers(VectorHandler::DDERequestHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DDERequestHandler,callbackData));
			break;
		case WM_DDE_TERMINATE :
			if(!installedHandlers(VectorHandler::DDETerminateHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DDETerminateHandler,callbackData));
			break;
		case WM_DDE_DATA :
			if(!installedHandlers(VectorHandler::DDEDataHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DDEDataHandler,callbackData));
			break;
		case MM_WOM_OPEN :
			if(!installedHandlers(VectorHandler::MMOpenHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MMOpenHandler,callbackData));
			break;
		case MM_WOM_CLOSE :
			if(!installedHandlers(VectorHandler::MMCloseHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MMCloseHandler,callbackData));
			break;
		case MM_WOM_DONE :
			if(!installedHandlers(VectorHandler::MMDoneHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MMDoneHandler,callbackData));
			break;
		case WM_LBUTTONDBLCLK :
			if(!installedHandlers(VectorHandler::LeftButtonDoubleHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::LeftButtonDoubleHandler,callbackData));
			break;
		case WM_LBUTTONDOWN :
			if(!installedHandlers(VectorHandler::LeftButtonDownHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::LeftButtonDownHandler,callbackData));
			break;
		case WM_LBUTTONUP :
			if(!installedHandlers(VectorHandler::LeftButtonUpHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::LeftButtonUpHandler,callbackData));
			break;
		case WM_RBUTTONDBLCLK :
			if(!installedHandlers(VectorHandler::RightButtonDoubleHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::RightButtonDoubleHandler,callbackData));
			break;
		case WM_RBUTTONDOWN :
			if(!installedHandlers(VectorHandler::RightButtonDownHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::RightButtonDownHandler,callbackData));
			break;
		case WM_RBUTTONUP :
			if(!installedHandlers(VectorHandler::RightButtonUpHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::RightButtonUpHandler,callbackData));
			break;
		case WM_NCLBUTTONUP :
			if(!installedHandlers(VectorHandler::NCLeftButtonUpHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::NCLeftButtonUpHandler,callbackData));
			break;
		case WM_NCLBUTTONDOWN :
			if(!installedHandlers(VectorHandler::NCLeftButtonDownHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::NCLeftButtonDownHandler,callbackData));
			break;
		case WM_NCRBUTTONUP :
			if(!installedHandlers(VectorHandler::NCRightButtonUpHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::NCRightButtonUpHandler,callbackData));
			break;
		case WM_NCRBUTTONDOWN :
			if(!installedHandlers(VectorHandler::NCRightButtonDownHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::NCRightButtonDownHandler,callbackData));
			break;
		case WM_MOUSEMOVE :
			if(!installedHandlers(VectorHandler::MouseMoveHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MouseMoveHandler,callbackData));
			break;
		case WM_SETFOCUS :
			if(!installedHandlers(VectorHandler::SetFocusHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::SetFocusHandler,callbackData));
			break;
		case WM_SETFONT :
			if(!installedHandlers(VectorHandler::SetFontHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::SetFontHandler,callbackData));
			break;
		case WM_KILLFOCUS :
			if(!installedHandlers(VectorHandler::KillFocusHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::KillFocusHandler,callbackData));
			break;
		case WM_KEYUP :
			if(!installedHandlers(VectorHandler::KeyUpHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::KeyUpHandler,callbackData));
			break;
		case WM_KEYDOWN :
			if(!installedHandlers(VectorHandler::KeyDownHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::KeyDownHandler,callbackData));
			break;
		case WM_GETMINMAXINFO :
			if(!installedHandlers(VectorHandler::MinMaxHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MinMaxHandler,callbackData));
			break;
		case WM_ENTERIDLE :
			if(!installedHandlers(VectorHandler::EnterIdleHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::EnterIdleHandler,callbackData));
			break;
		case WM_MENUSELECT :
			if(!installedHandlers(VectorHandler::MenuSelectHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MenuSelectHandler,callbackData));
			break;
		case WM_GETDLGCODE :
			if(!installedHandlers(VectorHandler::DialogCodeHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DialogCodeHandler,callbackData));
			break;
		case WM_MEASUREITEM :
			if(!installedHandlers(VectorHandler::MeasureItemHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::MeasureItemHandler,callbackData));
			break;
		case WM_VSCROLL :
		  if(!installedHandlers(VectorHandler::VerticalScrollHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::VerticalScrollHandler,callbackData));
			break;
		case WM_HSCROLL :
		  if(!installedHandlers(VectorHandler::HorizontalScrollHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::HorizontalScrollHandler,callbackData));
			break;
#if defined(__FLAT__)
		case WM_NOTIFY :
			if(!installedHandlers(VectorHandler::NotifyHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::NotifyHandler,callbackData));
			break;
#endif
		case WM_SIZE :
			if(!installedHandlers(VectorHandler::SizeHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::SizeHandler,callbackData));
			break;
		case WM_DROPFILES :
		  if(!installedHandlers(VectorHandler::DropFilesHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DropFilesHandler,callbackData));
			break;
		case WM_DESTROY :
			if(!installedHandlers(VectorHandler::DestroyHandler))break;
			callbackData.hookReturnCode(callHandlers(VectorHandler::DestroyHandler,callbackData));
			break;
		case WM_NCDESTROY :
		default :
      callbackData.hookReturnCode(FALSE);
			break;
	}
	return callbackData;
}
