//============================================================
// Program:		WindowFrame
// Description:	Class for simplifying the window setup process
// Author:		Benjamin Gottemoller
// Website:		http://www.particlefield.com
// Date:		4/20/01
// Legal:		Licensed under the gnu GPL (see gpl.txt for details)
//============================================================

#include "WindowFrame.h"
#include <windows.h>
#include <windowsx.h>
#include <math.h>
#include <iostream.h> 
#include <mmsystem.h>

#include "GFDebugHandler.h"

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

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

WindowFrame::WindowFrame(char *program_name, bool debug_detail)
{
	ProgramName		= program_name;
	WinHandle		= NULL;
	ZeroMemory(&WinClass, sizeof(WinClass));
	ZeroMemory(&WinInstance, sizeof(WinInstance));
	WinName				= NULL;
	Width				= 0;
	Height				= 0;
	run_main_loop		= 0;
	state_toggle		= 0;
	start_time			= 0;
	frame_count			= 0;
	time_diff			= 0;
	last_time			= 0;
	counter_frequency	= 0;
	FPS					= 0;
	IsGamePaused		= 0;
	IsGameLocked		= 0;

	memset(LocalPath, NULL, MAX_PATH + 256);
	GetModuleFileName(NULL, LocalPath, MAX_PATH + 256);
	for(int i=MAX_PATH + 255; i>=0; i--)
	{
		if(LocalPath[i] != '\\')
		{
			LocalPath[i] = NULL;
		}
		else
		{
			break;
		}
	}

	InitDebugger(ProgramName, LocalPath, NULL, debug_detail);
}

WindowFrame::~WindowFrame()
{
	if(state_toggle)
	{
		DestroyWindow();	
		state_toggle = 0;
	}

	CloseDebugger();
}

void WindowFrame::BeginWindow(HINSTANCE hInst, char *name, WNDPROC msg_proc, int width, int height, int bk_color)
{
	if(state_toggle)
	{
		DestroyWindow();	
		state_toggle = 0;
	}

	if(width == -1) width = GetSystemMetrics(SM_CXSCREEN);
	if(height == -1) height = GetSystemMetrics(SM_CYSCREEN);

	WinInstance = hInst;
	Width = width;
	Height = height;
	WinName = name;

	WinClass.cbSize			= sizeof(WNDCLASSEX);
	WinClass.style			= CS_CLASSDC;
	WinClass.lpfnWndProc	= MsgProc;
	WinClass.cbClsExtra		= 0;
	WinClass.cbWndExtra		= 0;
	WinClass.hInstance		= WinInstance;
	WinClass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	WinClass.hCursor		= LoadCursor(NULL, IDC_ARROW);
	WinClass.hbrBackground	= (HBRUSH) GetStockObject(bk_color);
	WinClass.lpszMenuName	= NULL;
	WinClass.lpszClassName	= WinName;
	WinClass.hIconSm		= NULL;

	RegisterClassEx(&WinClass);
	WinHandle = CreateWindow(WinName, WinName, 
							 WS_MAXIMIZE, 0, 0, Width, Height, 
							 NULL, NULL, WinClass.hInstance, NULL);

	Confirm(WinHandle != NULL);

	program_start_time = 0;
	start_time = 0;
	frame_count = 0;
	time_diff = 0;
	last_time = 0;
	QueryPerformanceFrequency((LARGE_INTEGER*)&counter_frequency);
	FPS = 0;
	IsGamePaused = 0;
	IsGameLocked = 0;

	state_toggle = 1;
}

void WindowFrame::DestroyWindow(void)
{
	if(state_toggle)
	{
		UnregisterClass(WinName, WinClass.hInstance);
	}

	state_toggle = 0;
	IsGamePaused = 0;
	IsGameLocked = 0;
}

void WindowFrame::StartMainLoop(void (*loop_func)(void))
{
	MSG msg;
	ZeroMemory(&msg, sizeof(msg));
	run_main_loop = 1;

	QueryPerformanceCounter((LARGE_INTEGER*)&program_start_time);

	while((msg.message != WM_QUIT) && (run_main_loop))
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			__int64 time = 0;
			double fps_time_diff = 0;
			if(last_time == 0)
			{
				QueryPerformanceCounter((LARGE_INTEGER*)&last_time);
			}

			QueryPerformanceCounter((LARGE_INTEGER*)&time);
			time_diff = (float)((double)(time - last_time) / (double)counter_frequency);
			last_time = time;
			if(IsGamePaused) time_diff = 0;

			fps_time_diff = (double)(time - start_time) / (double)counter_frequency;
			if((start_time == 0) || (fps_time_diff > 0.250)) 
			{
				FPS = (float)((double)frame_count / fps_time_diff);
				frame_count = 0;
				start_time = time;
			}
			frame_count++;

			loop_func();
		}
	}
}

void WindowFrame::StopMainLoop(void)
{
	run_main_loop = 0;
}



