#include <windows.h>

#include "../Daodan.h"
#include "../Daodan_Config.h"
#include "Input.h"
#include "Win32.h"

#include "../Oni/Oni.h"


// LIrPlatform_Terminate wrapper. Removes any cursor clipping we've done. Doing
// this is required for Windows 98 :-D
void ONICALL DD_LIrPlatform_Terminate(void)
{
	ClipCursor(NULL);
	LIrPlatform_Terminate();
}

// LIrPlatform_Mode_Set wrapper. Clips cursor to window bounds to
// prevent loosing focus (mostly on Linux).
void ONICALL DD_LIrPlatform_Mode_Set(unsigned int active_mode)
{
	DDmAssert(ONgPlatformData.Window);

	if (active_mode)
	{
		RECT rc;
		POINT pt;

		pt.x = 0;
		pt.y = 0;

		if (GetClientRect(ONgPlatformData.Window, &rc) &&
			ClientToScreen(ONgPlatformData.Window, &pt))
		{
			rc.left   += pt.x;
			rc.top    += pt.y;
			rc.right  += pt.x;
			rc.bottom += pt.y;

			ClipCursor(&rc);
		}
	}
	else
	{
		ClipCursor(NULL);
	}

	LIrPlatform_Mode_Set(active_mode);
}

BOOL WINAPI DD_GetCursorPos(LPPOINT lpPoint)
{
	DDmAssert(ONgPlatformData.Window);
	
	return GetCursorPos(lpPoint) && ScreenToClient(ONgPlatformData.Window, lpPoint);
}

BOOL WINAPI DD_SetCursorPos(int X, int Y)
{
	POINT pt;
	pt.x = X;
	pt.y = Y;
	
	DDmAssert(ONgPlatformData.Window);
	
	return ClientToScreen(ONgPlatformData.Window, &pt) && SetCursorPos(pt.x, pt.y);
}

static LRESULT CALLBACK DD_ONrPlatform_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		case WM_SYSCOMMAND:
			if (wParam == SC_SCREENSAVE)
			{
				// Prevent screen saver from starting when Oni has focus.
				return 0;
			}
			break;
		
		case WM_PAINT:
		{
			PAINTSTRUCT ps;
			BeginPaint(hWnd, &ps);
			// Oni does a useless PatBlt here.
			EndPaint(hWnd, &ps);
			return 0;
		}
		
		case WM_CLOSE:
			// There's no way to reliably terminate a modal dialog.
			// The following condition is (almost) always true.
			if (WMgActive)
				exit(0);

			ONgTerminateGame = UUcTrue;
			return 0;
			
		case WM_SETCURSOR:
			// If a mouse is inside our client area, we hide cursor (always),
			// otherwise we ask DefWindowProc to set an appropriate arrow for us.
			if (LOWORD(lParam) == HTCLIENT)
			{
				SetCursor(NULL);
				return TRUE;
			}

			break;
	}

	LRESULT res;
	if (DDrInput_WindowProc(hWnd, uMsg, wParam, lParam, &res))
		return res;

	return ONrPlatform_WindowProc(hWnd, uMsg, wParam, lParam);
}


UUtError ONICALL DD_ONrPlatform_Initialize(ONtPlatformData *PlatformData)
{
 	WNDCLASSEX WndClass;
 	RECT Rect;
 	const int Width = 640, Height = 480;
	DWORD window_style, window_style_ex;
 
	PlatformData->Instance = ONgInstance;
	PlatformData->Window   = NULL;
	
	if (FindWindow("ONI ", "ONI "))
	{
		AUrMessageBox(1, "Daodan: There is already an instance of the game running.");
		exit(0);
	}
	
	WndClass.cbSize        = sizeof(WndClass);
	WndClass.style         = CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
	WndClass.cbClsExtra    = 0;
	WndClass.cbWndExtra    = 0;
	WndClass.hInstance     = PlatformData->Instance;
	WndClass.hCursor       = NULL; // To debug: LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon         = LoadIcon(ONgInstance, MAKEINTRESOURCE(103));
	WndClass.hIconSm       = LoadIcon(ONgInstance, MAKEINTRESOURCE(103));
	WndClass.hbrBackground = GetStockObject(BLACK_BRUSH);
	WndClass.lpszMenuName = NULL;
	WndClass.lpszMenuName  = NULL;
 	WndClass.lpszClassName = "ONI ";
	WndClass.lpfnWndProc   = DD_ONrPlatform_WindowProc;
 
 	RegisterClassEx(&WndClass);
 	
	if (M3gResolutionSwitch)
	{
		// Do not allow border and topmost flag for a fullscreen window.
		window_style    = WS_POPUP;
		window_style_ex = 0;
	}
	else
	{
		ConfigOption_t* co = DDrConfig_GetOptOfType("windows.border", C_BOOL);
		int opt_border = 0;
		if (co && co->value.intBoolVal)
			opt_border = 1;
		co = DDrConfig_GetOptOfType("windows.topmost", C_BOOL);
		int opt_topmost = 0;
		if (co && co->value.intBoolVal)
			opt_topmost = 1;

		window_style    = (opt_border) ? WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_DLGFRAME | WS_MINIMIZEBOX : WS_POPUP;
		window_style_ex = (opt_topmost) ? WS_EX_TOPMOST : 0;
	}
	
 	Rect.left = (GetSystemMetrics(SM_CXSCREEN) / 2) - (Width / 2);
 	Rect.top = (GetSystemMetrics(SM_CYSCREEN) / 2) - (Height / 2);
 	Rect.right = Rect.left + Width;
 	Rect.bottom = Rect.top + Height;
	AdjustWindowRectEx(&Rect, window_style, FALSE, window_style_ex);
	
	PlatformData->Window = CreateWindowEx(window_style_ex, WndClass.lpszClassName, "ONI ", window_style,
		Rect.left, Rect.top, Rect.right - Rect.left, Rect.bottom - Rect.top,
		NULL, NULL, PlatformData->Instance, NULL);
	
 	ShowWindow(PlatformData->Window, SW_SHOWNORMAL);
 	UpdateWindow(PlatformData->Window);
 
	return UUcError_None;
 }

