#ifdef WIN32
//Windows screensaver code borrowed from Rachel Grey
// http://www.cityintherain.com/howtoscr.html

#include <direct.h>
#include <windows.h>
#include <scrnsave.h>
#include <GL/gl.h>
#include <GL/glu.h>

//Includes from main.cpp
#include "globals.h"
#include "DNA.h"
#include "World.h"
#include "Jungle.h"

int config();
bool draw();
void display();
void timer( int );
void kdone( unsigned char, int, int );
void mdone( int, int );
void load();
void loadsettings();
void savesettings();
int save();

extern World* world;
extern Settings settings;
extern FSettings fsettings;
//^Includes from main.cpp^

//globals used by the function below to hold the screen size
int Width;	
int Height;

//define a Windows timer 
#define TIMER 1 


static void InitGL(HWND hWnd, HDC & hDC, HGLRC & hRC)
{
  PIXELFORMATDESCRIPTOR pfd;
  ZeroMemory( &pfd, sizeof pfd );
  pfd.nSize = sizeof pfd;
  pfd.nVersion = 1;
  pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  pfd.iPixelType = PFD_TYPE_RGBA;
  pfd.cColorBits = 24;
  
  hDC = GetDC( hWnd );
  
  int i = ChoosePixelFormat( hDC, &pfd );  
  SetPixelFormat( hDC, i, &pfd );

  hRC = wglCreateContext( hDC );
  wglMakeCurrent( hDC, hRC );

}
 
static void CloseGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
  wglMakeCurrent( NULL, NULL );
  wglDeleteContext( hRC );
  ReleaseDC( hWnd, hDC );
}

// Screen Saver Procedure
LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT message, 
                               WPARAM wParam, LPARAM lParam)
{
  static HDC hDC;
  static HGLRC hRC;
  static RECT rect;

  switch ( message ) {

  case WM_CREATE: 
    // get window dimensions
    GetClientRect( hWnd, &rect );
    Width = rect.right;		
    Height = rect.bottom;
    
    //get configuration from registry if applicable
	chdir( getenv( "SystemRoot" ) );
 	chdir( "system32" );
	loadsettings();

	if ( Width < 400 ) //we're in preview mode
		settings.zoom *= 6;

    //set up OpenGL
    InitGL( hWnd, hDC, hRC );

    //Initialize perspective, viewpoint, and
    //any objects you wish to animate
	if ( settings.lizard ) world = new Jungle();
	else world = new World();
	load();
	if ( settings.AA )
	{
		// Thanks to Adrian for making this work!
		// And thanks to Matt for helping me test the problem that
		// manifested only on his machine and noplace else.
		glEnable( GL_BLEND );
		glEnable( GL_POLYGON_SMOOTH );
		if ( settings.AAline) glEnable( GL_LINE_SMOOTH );
		glBlendFunc (GL_SRC_ALPHA, GL_ONE);
		glHint( GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE );
	}

	glShadeModel( settings.shade ? GL_SMOOTH : GL_FLAT );

    //create a timer that ticks every 10 milliseconds
    SetTimer( hWnd, TIMER, 10, NULL ); 
    return 0;
 
  case WM_DESTROY:
    KillTimer( hWnd, TIMER );
    
    //delete any objects created during animation
    //and close down OpenGL nicely
	chdir( getenv( "SystemRoot" ) );
 	chdir( "system32" );
	save();
	delete world;

    CloseGL( hWnd, hDC, hRC );
    return 0;

  case WM_TIMER:
    //call some function to advance your animation
    world->Step();
	if ( draw() )
	{
		SwapBuffers( hDC );
		glFlush();
	}
    return 0;

  //handle special keypresses
  case WM_KEYDOWN:
	  	switch ( wParam )
		{
		case 'c':
		case 'C':
			switch( settings.camera )
			{
			case C_WORLD: settings.camera = C_CHASE; return 0;
			case C_GRAPH: settings.camera = C_WORLD; return 0;
			case C_CHASE: settings.camera = C_GRAPH; 
				int rc = world->rgcount;
				world->rgcount = 1;
				world->RenderGraph();
				SwapBuffers( hDC );
				glFlush();
				world->rgcount = rc;
			}
			return 0;
		case 'v':
		case 'V':
			world->ViewChange();
			return 0;
		case '+':
		case '=':
		case VK_ADD:
			if ( settings.zoom < 1000 ) settings.zoom += 5;
			return 0;
		case '_':
		case '-':
		case VK_SUBTRACT:
			if ( settings.zoom > 10 ) settings.zoom -= 5;
			return 0;
		}
  case WM_KEYUP:
	  switch ( wParam )
	  {
		case 'c':
		case 'C':
		case 'V':
		case 'v':
		case '+':
		case '=':
		case '_':
		case '-':
		case VK_ADD:
		case VK_SUBTRACT:
			return 0;
	  }
  //let the screensaver library take care of any
  //other messages
  }
  return DefScreenSaverProc( 
    hWnd, message, wParam, lParam );
}

BOOL WINAPI
ScreenSaverConfigureDialog(HWND hDlg, UINT message, 
                           WPARAM wParam, LPARAM lParam)
{
	return true;
}

// needed for SCRNSAVE.LIB
BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
	chdir( getenv( "SystemRoot" ) );
 	chdir( "system32" );
  	loadsettings();
	savesettings();

	STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
	GetStartupInfo( &si );
	si.dwFlags |= STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_SHOWNORMAL;

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( !CreateProcess( NULL, // No module name (use command line). 
        "notepad Genesaver.cfg", // Command line. 
        NULL,             // Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        FALSE,            // Set handle inheritance to FALSE. 
        0,                // No creation flags. 
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi )             // Pointer to PROCESS_INFORMATION structure.
    ) 
    {
        return false;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );

	return true;
}

#endif //WIN32