/*****************************************************************************
Name            :   frontend.c
Title           :   Frontend

Copyright       :   1992 by VideoLogic Limited. All rights reserved.
		    No part of this software, either material or conceptual
		    may be copied or distributed, transmitted, transcribed,
		    stored in a retrieval system or translated into any
		    human or computer language in any form by any means,
		    electronic, mechanical, manual or other-wise, or
		    disclosed to third parties without the express written
		    permission of VideoLogic Limited, HomePark Estate,
		    King's Langley, Hertfordshire, WD4 8LZ, U.K.

Description		:   Windows frontend including WinMain()
Program Type    :   Microsoft Visual C++ V2
Notes:			:   The distance units used in this file are supposed to 
				    approximate metres.	The initial lighting is sunlight 
				    (not headlight).  Strange results may occur if Windows 
				    has been running for 50 days due to clock wraparound.
*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <windows.h>
#include <mmsystem.h> 
#include <windowsx.h>
  
#include "ddraw.h"

#define Cplusplus

#include "sgl.h"
#include "config.h"
#include "frontend.h"
#include "resource.h"
#include "textower.h"

#define NAME "TexTower"
#define TITLE "TexTower using DirectDraw"

#define DO_FRAME_RATE  TRUE

/* Globals */

GLOBALVARS 			globalVars;
static HINSTANCE  	hInst;
static HWND  		hWnd;
BOOL				bActive;
DWORD 				LastError;
extern "C" BOOL 				bInfo;
extern "C" sgl_versions*		versions;
extern "C" sgl_win_versions*	w32versions;
BOOL				bQuit=FALSE;
int					nStrictLocks;

/*int camera;*/

static float  fFramesPerSec = 0.0f;
static sgl_colour 	White	 =	{1.0f,1.0f,1.0f};
 
extern BOOL Shads,Paws,Ress, VPort;
extern sgl_vector	ParLightDir ;
extern int cammy,light1,light2;


/* Callback prototype */

extern "C" int sgl_2d_callback(P_CALLBACK_SURFACE_PARAMS lpSurfaceInfo);
int eor_callback();


/*****************************************************************
* Function Name		: WinMain  
******************************************************************/

int PASCAL WinMain ( HANDLE hInstance,
					 HANDLE hPrevInstance,
					 LPSTR  lpszCmdParam,
					 int    nCmdShow )
{
	static char szAppName[] = "SGLFrontEnd";
	HWND        hwnd;
	MSG         msg;
	WNDCLASS    wndclass;
	HMENU       hMenu;
	LOGBRUSH    brush;
	int			iret;
	int			loopcount;

	/* Get Version info */

	versions = sgl_get_versions();
	w32versions = sgl_get_win_versions();

	/* setup inital values */

	hInst = hInstance;

	brush.lbStyle = BS_SOLID;
	brush.lbColor = PALETTEINDEX(DEFAULT_KEY_COLOUR);

	/* set the key value for overlay */

	globalVars.hBrush    = CreateBrushIndirect(&brush);
	globalVars.keyColour = DEFAULT_KEY_COLOUR;
	

	/* WINDOWS APPLICATION STUFF */

	if (!hPrevInstance)
	{
		wndclass.style = 0; 
	    wndclass.lpfnWndProc = WndProc;
	    wndclass.cbClsExtra = 0;
	    wndclass.cbWndExtra = 0;
	    wndclass.hInstance = hInstance;
	    wndclass.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
	    wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
	    wndclass.hbrBackground = globalVars.hBrush; 
	    wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
	    wndclass.lpszClassName = NAME;
		RegisterClass (&wndclass);
	}

	hMenu = LoadMenu(hInstance,MAKEINTRESOURCE(IDR_MENU1));

    hwnd = CreateWindowEx(0,
				    NAME,
				    TITLE,
				    WS_POPUP|WS_VISIBLE,
				    0, 0,
				    GetSystemMetrics( SM_CXSCREEN ),
				    GetSystemMetrics( SM_CYSCREEN ),
				    NULL,
				    hMenu,
				    hInstance,
				    NULL );

	if (hwnd == NULL)
	{
		LastError = GetLastError();
		return FALSE;
	}

	/*
	This may be needed for maximum compatibility
	nStrictLocks = GetPrivateProfileInt("Default","StrictLocks",1,"sglhw.ini");
	*/
	nStrictLocks = 0 ;

	/* Put sgl into direct draw mode */

	iret =  sgl_use_ddraw_mode (hwnd, &sgl_2d_callback);

	if (iret !=	sgl_no_err)
	{
		ShowWindow(hwnd,SW_HIDE);
		MessageBox(NULL,"ERROR : sgl_use_ddraw_mode failed","tower.exe",MB_OK);
		DestroyWindow(hwnd);
		return FALSE;
	}

	/* Set up the SGL scene	*/

	SetupScene(hwnd, (WORD)globalVars.keyColour);

	bActive = TRUE;

	if (nStrictLocks)
	{
		loopcount = 100;

		/* Do normal message loop for a while to
		   allow GDI to draw the window	*/

		while (loopcount--)
	    {
	      	if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
	        {
	            if (!GetMessage( &msg, NULL, 0, 0 ))
	            {
	                return msg.wParam;
	            }

	            TranslateMessage(&msg); 
	            DispatchMessage(&msg);
	        }
	    }

		/* Do main message loop inside the callback */

		iret = sgl_use_eor_callback(&eor_callback);

		while (!bQuit)
		  	NextFrame();

		Sleep(100);
		Finish();
	}
	else
	{
		/* Strict locking is off, so use normal message loop */

		while (1)
	    {
	      	if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
	        {
	            if (!GetMessage( &msg, NULL, 0, 0 ))
	            {
					Finish();
					break;

	                /* return msg.wParam; */
	            }

	            TranslateMessage(&msg); 
	            DispatchMessage(&msg);
	        }
	        else if (bActive)
	            NextFrame();
   			else
				WaitMessage();
	    }
	}

	return 0;
}


/*****************************************************************
* Function Name		: eor_callback  
* Inputs			: none
* Outputs			: none
* Returns			: constant 
* Description		: End of render callback.
					  As soon as the buffer is unlocked Windows 
					  can process it's message loop.
					  If this were not done here then Windows would 
					  wait for the Direct Draw unlock before 
					  updating it's display; and we want to remove
					  all wait states! 
******************************************************************/	

int eor_callback()
{
	MSG         msg;

	while(1)
	{
	  	if (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
	    {
	        if (!GetMessage( &msg, NULL, 0, 0 ))
	        {
				/* Application closing down */

				bQuit = TRUE;

				/* Prevent sgl from rendering */

	            return 1;
	        }

	        TranslateMessage(&msg); 
	        DispatchMessage(&msg);
	    }

		Sleep(5); // Allow the mouse some time to move 

		if (bActive)
		{
			break; // If active then continue to render 	
		}
	}

	return 0; // Continue with sgl_render 

}


/*****************************************************************
* Function Name		: WndProc  
******************************************************************/

long FAR PASCAL WndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{

	hWnd = hwnd;

	switch (message)
	{
	    case WM_ACTIVATEAPP:
		{
	        bActive = (BOOL)wParam;
	        break;
		}
		
		case WM_CREATE:
		{
			return 0;
		}

		case WM_DESTROY:
		{
			bQuit = TRUE;	
			PostQuitMessage (0);
			return 0;
		}

	   case WM_KEYDOWN:
			/* f1 */
	        switch(wParam)
	        {
		        /* case VK_ESCAPE: */

		        case VK_F1:
					cammy = 3;

		            break;

		        case VK_F2:
					cammy = 1;

		            break;

		        case VK_F3:
					cammy = 2;

		            break;

		        case VK_F4:
					cammy = 4;

		            break;
		        case VK_F5:
					cammy = 5;

		            break;
		        case VK_F6:
					cammy = 6;

		            break;

		        case VK_F7:
					cammy = 7;
					break;

		        case 83:

					if (Shads)
					{
						sgl_set_parallel_light (light1,  White, ParLightDir, FALSE, FALSE);
						Shads = FALSE;
					}
					else
					{

						sgl_set_parallel_light (light1,  White, ParLightDir, TRUE, FALSE);						
						Shads = TRUE;
					}
					break;

		        case 80:

					Paws=!Paws;
		
		            break;

		        case 82:

					Ress=TRUE;
		
		            break;

				case 86:
					VPort=!VPort;

					break;

				/* f1 for info */

		        case VK_F8:
				{
					/* Get Version/Status info again */

					versions = sgl_get_versions();
					w32versions = sgl_get_win_versions();

					/* Display version info in 2d callback */

					bInfo = !bInfo;
		            break;
				}


				/* f12 to quit */

		        case VK_F12:
				{
					bActive = FALSE;// This interlock fixed the hanging bug !!!!

					/* Wait for main message loop to see bActive going low */

					Sleep(100);
							
		            PostMessage(hWnd, WM_CLOSE, 0, 0);
		            break;
				}	
	        }
	        break;
	}

	return DefWindowProc (hwnd, message, wParam, lParam);
}

