//-------------------------------------------------- 
// Title:		FieldEngine
// Author:		Tony Kim 
// Date:		2006 Nov 10 
// Description: Mainly background overhead
//-------------------------------------------------- 

#pragma once
#include "FieldEngine.h"

//-------------------------------------------------- 
// Static Variable Initialization
//-------------------------------------------------- 
FieldEngine *FieldEngine::m_pFieldEngine = NULL;

//-------------------------------------------------- 
// Windows Functions
//-------------------------------------------------- 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
{
	MSG			msg;
	static int	iTickTrigger = 0;
	int			iTickCount;

	if( Initialize(hInstance) )
	{
		// Initialize FieldEngine
		if( !FieldEngine::GetEngine()->Initialize(iCmdShow) )
			return FALSE;
		
		// Enter main message loop
		while( TRUE )
		{
			if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
			{
				// Process the message
				if( msg.message == WM_QUIT )
					break;
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
				// Make sure we're not sleeping
				if( !FieldEngine::GetEngine()->GetSleep() )
				{
					// Establish proper timing
					iTickCount = GetTickCount();
					if( iTickCount > iTickTrigger )
					{
						iTickTrigger = iTickCount + FieldEngine::GetEngine()->GetFrameDelay();
						Cycle();
					}
				}
			}
		}
		return (int)msg.wParam;
	}

	// End application
	End();

	return TRUE;
}

LRESULT CALLBACK WndProc( HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
{
	// Route all messages to the main engine
	return FieldEngine::GetEngine()->HandleEvent(hWindow, msg, wParam, lParam);
}

//-------------------------------------------------- 
// FieldEngine Constructor/Destructor
//-------------------------------------------------- 
FieldEngine::FieldEngine( HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle, WORD wIcon, WORD wSmallIcon, int iWidth, int iHeight)
{
	// Set the member variables for the engine
	m_pFieldEngine = this;
	m_hInstance = hInstance;
	m_hWindow = NULL;
	if( lstrlen(szWindowClass) > 0 )
		lstrcpy(m_szWindowClass, szWindowClass);
	if( lstrlen(szTitle) > 0 )
		lstrcpy(m_szTitle, szTitle);
	m_wIcon = wIcon;
	m_wSmallIcon = wSmallIcon;
	m_iWidth = iWidth;
	m_iHeight = iHeight;
	m_iFrameDelay = 50; // 20 FPS default
	m_bSleep = TRUE;
}

FieldEngine::~FieldEngine()
{
}

//-------------------------------------------------- 
// FieldEngine General Methods
//-------------------------------------------------- 

BOOL FieldEngine::Initialize(int iCmdShow)
{
	WNDCLASSEX	wndclass;

	// Create the window class for the main window
	wndclass.cbSize			= sizeof(wndclass);
	wndclass.style			= CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc	= WndProc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= m_hInstance;
	wndclass.hIcon			= LoadIcon(m_hInstance, MAKEINTRESOURCE(GetIcon()));
	wndclass.hIconSm		= LoadIcon(m_hInstance, MAKEINTRESOURCE(GetSmallIcon()));
	wndclass.hCursor		= LoadCursor( NULL, IDC_ARROW );
	wndclass.hbrBackground	= (HBRUSH)(COLOR_WINDOW + 1);
	wndclass.lpszMenuName	= NULL;
	wndclass.lpszClassName	= m_szWindowClass;

	// Register window class
	if( !RegisterClassEx( &wndclass ) )
		return FALSE;

	// Calculate the window size and position
	int iWindowWidth = m_iWidth + GetSystemMetrics(SM_CXFIXEDFRAME)*2,
		iWindowHeight = m_iHeight + GetSystemMetrics(SM_CYFIXEDFRAME)*2 + GetSystemMetrics(SM_CYCAPTION);
	if( wndclass.lpszMenuName != NULL )
		iWindowHeight += GetSystemMetrics(SM_CYMENU);
	
	int iXWindowPos = (GetSystemMetrics(SM_CXSCREEN) - iWindowWidth) / 2,
		iYWindowPos = (GetSystemMetrics(SM_CYSCREEN) - iWindowHeight) / 2;

	// Create the window
	m_hWindow = CreateWindow( m_szWindowClass, m_szTitle, WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX, iXWindowPos, iYWindowPos, iWindowWidth, iWindowHeight, NULL, NULL, m_hInstance, NULL);
	if( !m_hWindow )
		return FALSE;

	// Show and update window
	ShowWindow(m_hWindow, iCmdShow);
	UpdateWindow(m_hWindow);

	return TRUE;
}

LRESULT FieldEngine::HandleEvent( HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_LBUTTONDOWN:
		// Handle left mouse button press
		MouseButtonDown(LOWORD(lParam), HIWORD(lParam), TRUE);
		return 0;

	case WM_LBUTTONUP:
		// Handle left mouse button release
		MouseButtonUp(LOWORD(lParam), HIWORD(lParam), TRUE);
		return 0;

	case WM_RBUTTONDOWN:
		// Handle right button press
		MouseButtonDown(LOWORD(lParam), HIWORD(lParam), FALSE);
		return 0;

	case WM_RBUTTONUP:
		// Handle right mouse button release
		MouseButtonDown(LOWORD(lParam), HIWORD(lParam), FALSE);
		return 0;

	case WM_MOUSEMOVE:
		// Handle mouse movement
		MouseMove(LOWORD(lParam), HIWORD(lParam));
		return 0;
	
	case WM_CREATE:
		// Set window and start
		SetWindow( hWindow );
		Start( hWindow );
		return 0;

	case WM_SETFOCUS:
		// Activate application and update sleep status
		Activate( hWindow );
		SetSleep( FALSE );
		return 0;

	case WM_KILLFOCUS:
		// Deactivate application and update sleep status
		Deactivate( hWindow );
		SetSleep( TRUE );
		return 0;

	case WM_PAINT:
		HDC			hDC;
		PAINTSTRUCT ps;
		hDC = BeginPaint( hWindow, &ps );
		
		EndPaint( hWindow, &ps );
		return 0;

	case WM_DESTROY:
		// End application
		End();
		PostQuitMessage(0);
		return 0;
	}

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