#include "StdAfx.h"
#include "GameWindow.h"

#include <windowsx.h>
#include <assert.h>

#include <string>

using namespace std;

LRESULT ELGameWindow_MessageHandler::OnDispatchMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

class ELGameWindow_DefaultMessageHandler : public ELGameWindow_MessageHandler
{
public:
	ELGameWindow_DefaultMessageHandler() {}
	virtual ~ELGameWindow_DefaultMessageHandler() {}

	virtual void OnIdle()
	{}
};

ELGameWindow_MessageHandler& ELGameWindow_GetDefaultMessageHandler()
{
	static ELGameWindow_DefaultMessageHandler s_kDefMsgHandler;
	return s_kDefMsgHandler;
}

LRESULT WINAPI ELGameWindow_OnDispatchMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

static const char* EL_GAMEWINDOW_CLASSNAME = "ELApplication";

static ELGameWindow_MessageHandler* gs_pkMsgHandler = &ELGameWindow_GetDefaultMessageHandler();
static HWND gs_hWnd = NULL;

static struct ELGameWindowInitConfig
{
	string st_title;
	unsigned width;
	unsigned height;
	bool isCenter;
	bool isEnableIdle;

	ELGameWindowInitConfig()
	{
		st_title = "eter.game";
		width = 640;
		height = 480;
		isCenter = true;
		isEnableIdle = true;
	}
} gs_initConfig;

static const WNDCLASSEX EL_GAMEWINDOW_WNDCLASSEX = 
{ 
	sizeof(WNDCLASSEX), CS_CLASSDC, ELGameWindow_OnDispatchMessage, 
	0L, 0L, GetModuleHandle(NULL), NULL, NULL, 
	(HBRUSH)GetStockObject(BLACK_BRUSH), NULL,
	EL_GAMEWINDOW_CLASSNAME, NULL 
};

HWND ELGameWindow_GetHandle()
{
	return gs_hWnd;
}

HDC		ELGameWindow_GetDC()
{
	return GetDC(gs_hWnd);
}

void	ELGameWindow_ReleaseDC(HDC hDC)
{
	ReleaseDC(gs_hWnd, hDC);
}

void ELGameWindow_SetMessageHandler(ELGameWindow_MessageHandler& msgHandler)
{
	gs_pkMsgHandler = &msgHandler;	
}

LRESULT WINAPI ELGameWindow_OnDispatchMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	assert(NULL != gs_pkMsgHandler);
	return gs_pkMsgHandler->OnDispatchMessage(hWnd, msg, wParam, lParam);
}

void ELGameWindow_Show()
{
	ShowWindow(gs_hWnd, SW_SHOW);
}

void ELGameWindow_Hide()
{
	ShowWindow(gs_hWnd, SW_HIDE);
}

void ELGameWindow_Loop()
{
	MSG msg; 
	while(1)
	{
		if (gs_initConfig.isEnableIdle)
		{
			if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
			{
				if (!GetMessage(&msg, NULL, 0, 0 ))
					break;
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
				if (gs_pkMsgHandler)
					gs_pkMsgHandler->OnIdle();
			}
		}
		else
		{
			if (!GetMessage(&msg, NULL, 0, 0 ))
				break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
}

void	ELGameWindow_AdjustWindowSize(int width, int height)
{
	RECT oldRect;
	GetWindowRect(gs_hWnd, &oldRect);

	RECT newRect;
	SetRect(&newRect, 0, 0, width, height);
		
	AdjustWindowRectEx(&newRect,
		GetWindowStyle(gs_hWnd),     
		GetMenu(gs_hWnd) != NULL,    
		GetWindowExStyle(gs_hWnd ) ); 

	SetWindowPos(gs_hWnd, NULL, 0, 0, newRect.right-newRect.left, newRect.bottom-newRect.top, SWP_NOMOVE|SWP_NOZORDER);	
	
}

bool ELGameWindow_Startup()
{
	RegisterClassEx(&EL_GAMEWINDOW_WNDCLASSEX);

	gs_hWnd = CreateWindow( 
		EL_GAMEWINDOW_CLASSNAME, gs_initConfig.st_title.c_str(), 
		WS_OVERLAPPEDWINDOW, 0, 0, 0, 0,
		GetDesktopWindow(), NULL, EL_GAMEWINDOW_WNDCLASSEX.hInstance, NULL );
	
	{
		RECT rect;
		SetRect(&rect, 0, 0, gs_initConfig.width, gs_initConfig.height);
		
		AdjustWindowRectEx(&rect,
			GetWindowStyle(gs_hWnd),     
			GetMenu(gs_hWnd) != NULL,    
			GetWindowExStyle(gs_hWnd ) ); 
		
		MoveWindow(gs_hWnd, 0, 0, rect.right - rect.left, rect.bottom - rect.top, FALSE);
	}

	if (gs_initConfig.isCenter)
	{
		RECT rect;
		GetClientRect(gs_hWnd, &rect);
		
		int window_width = rect.right - rect.left;
		int window_height = rect.bottom - rect.top;
		
		int screen_width = GetSystemMetrics(SM_CXSCREEN);
		int screen_height = GetSystemMetrics(SM_CYSCREEN);
		
		int center_x = (screen_width - window_width)/2;
		int center_y = (screen_height - window_height)/2;
		
		SetWindowPos(gs_hWnd, NULL, center_x, center_y, 0, 0, SWP_NOZORDER|SWP_NOSIZE);	
	}

	return true;
}

void ELGameWindow_Cleanup()
{
	UnregisterClass(EL_GAMEWINDOW_CLASSNAME, EL_GAMEWINDOW_WNDCLASSEX.hInstance);	
}
