// loc.cpp : Definiert den Einstiegspunkt für die Anwendung.
//

#include "stdafx.h"
#include "loc.h"
#include "locGL.h"


#define MAX_LOADSTRING 100

// Globale Variablen:
HINSTANCE	hInst;								// Aktuelle Instanz
TCHAR		szTitle[MAX_LOADSTRING];			// Titelleistentext
TCHAR		szWindowClass[MAX_LOADSTRING];		// Klassenname des Hauptfensters
int			width = 1024;
int			fsWidth = 800;
int			height = 768;
int			fsHeight = 600;
int			left = 100;
int			top = 100;
int			colDepth = 32;
int			dx = 0;
int			dy = 0;
int			dz = -400;
int			rx = 0;
int			ry = 0;
bool		fullScreen = false;
bool		draw = false;

// Vorwärtsdeklarationen der in diesem Codemodul enthaltenen Funktionen:
ATOM				MyRegisterClass(HINSTANCE hInstance);
BOOL				InitInstance(HINSTANCE, int);
LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
void				SetupPixelFormat();
bool				ChangeDisplayMode(HWND hWnd);



int APIENTRY _tWinMain(HINSTANCE hInstance,
					   HINSTANCE hPrevInstance,
					   LPTSTR    lpCmdLine,
					   int       nCmdShow)
{
 	// TODO: Hier Code einfügen.
	MSG msg;
	HACCEL hAccelTable;

	// Globale Zeichenfolgen initialisieren
	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
	LoadString(hInstance, IDC_LOC, szWindowClass, MAX_LOADSTRING);
	MyRegisterClass(hInstance);

	// Anwendungsinitialisierung ausführen:
	if (!InitInstance (hInstance, nCmdShow)) {
		return FALSE;
	}

	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_LOC);

	// Hauptmeldungsschleife:
	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		locRender();
		SwapBuffers(hDC);
	}

	return (int) msg.wParam;
}



//
//  FUNKTION: WndProc(HWND, unsigniert, WORD, LONG)
//
//  ZWECK:  Verarbeitet Meldungen vom Hauptfenster.
//
//  WM_COMMAND	- Verarbeiten des Anwendungsmenüs
//  WM_PAINT	- Zeichnen des Hauptfensters
//  WM_DESTROY	- Beenden-Meldung anzeigen und zurückgeben
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HGLRC hRC;
    static POINTS posOld;          // old position 
    static POINTS posNew;          // new position 

	switch (message) 
	{
	case WM_CREATE:
		hDC = GetDC(hWnd);
		SetupPixelFormat();
		hRC = wglCreateContext(hDC);
		if (!hRC) MessageBox(NULL, "wglCreateContext(hDC) failed", "Error", NULL);
		wglMakeCurrent(hDC, hRC);
		locInit(hDC);
		break;
	case WM_SIZE:
		height = HIWORD(lParam);
		width = LOWORD(lParam);
		locResize(width, height);
		break;
	case WM_PAINT:
		locResize(width,height);
		locRender();
		break;
	case WM_DESTROY:
		wglMakeCurrent(hDC, hRC);
		wglDeleteContext(hRC);
		PostQuitMessage(0);
		break;
    case WM_LBUTTONDOWN: 
        SetCapture(hWnd); 
        posOld = MAKEPOINTS(lParam); 
		break;
    case WM_RBUTTONDOWN: 
        SetCapture(hWnd); 
        posOld = MAKEPOINTS(lParam); 
		break;
    case WM_MOUSEMOVE: 
		posNew = MAKEPOINTS(lParam); 
        if (wParam & MK_LBUTTON) 
		{
			if (draw)
			{
						rx = posNew.x / 9 + 4;
						ry = posNew.y / 7 + 4;
						WaveMap[oldmap][rx][ry] = -0.15f;
						WaveMap[oldmap][rx+1][ry] = -0.1f;
						WaveMap[oldmap][rx-1][ry] = -0.1f;
						WaveMap[oldmap][rx][ry+1] = -0.1f;
						WaveMap[oldmap][rx][ry-1] = -0.1f;
			} else
			{
				dx += (posNew.x - posOld.x);
				dy += (posNew.y - posOld.y);
			}
		}	
        if (wParam & MK_RBUTTON) 
		{
			dz += (posOld.y - posNew.y);
		}	
		posOld = posNew;
		break;
    case WM_LBUTTONUP: 
        ReleaseCapture(); 
		break;
    case WM_RBUTTONUP: 
        ReleaseCapture(); 
		break;
	case WM_CHAR:
		{
			TCHAR tc = (TCHAR)wParam;
			switch(tc) {
				case 'f':
					if (!ChangeDisplayMode(hWnd))
						MessageBox(NULL, "Could not change Display Mode!", "Error", NULL);
					break;
				case 'q':
				case 27:
					PostQuitMessage(0);
					break;
				case '+':
					{
						char buffer[100];
						value += 0.1f;
						if (ANZRAIN<950) {ANZRAIN+= 10;}
						sprintf(buffer, "%0.1f", value);
						SetWindowText(hWnd, buffer);
					}
					break;
				case '-':
					{
						char buffer[100];
						value -= 0.1f;
						if (ANZRAIN>0) {ANZRAIN -= 10;}
						sprintf(buffer, "%0.1f", value);
						SetWindowText(hWnd, buffer);
					}
					break;
				case 'w':
					{
						rx = rand() % 95 + 3;
						ry = rand() % 95 + 3;
						WaveMap[oldmap][rx][ry] = -2.0f;
						WaveMap[oldmap][rx+1][ry] = -1.0f;
						WaveMap[oldmap][rx-1][ry] = -1.0f;
						WaveMap[oldmap][rx][ry+1] = -1.0f;
						WaveMap[oldmap][rx][ry-1] = -1.0f;
						WaveMap[oldmap][rx+1][ry-1] = -0.6f;
						WaveMap[oldmap][rx-1][ry+1] = -0.6f;
						WaveMap[oldmap][rx+1][ry+1] = -0.6f;
						WaveMap[oldmap][rx-1][ry-1] = -0.6f;
					}
					break;
				case 'r':
					{
						raindraw = !raindraw;
					}
					break;
				case 'p':
					{
						if (simplefragment)
						{
							cgGLEnableProfile(fragmentProfile);

							//bind the program
							cgGLBindProgram(fragmentProgram);
							cgGLDisableProfile(fragmentProfile);
							simplefragment = !simplefragment;
						} else
						{
							cgGLEnableProfile(fragmentProfile);

							//bind the program
							cgGLBindProgram(fragmentProgram2);
							cgGLDisableProfile(fragmentProfile);
							simplefragment = !simplefragment;
						}
					}
					break;
				case 'd':
					{
						draw = !draw;
					}
					break;
			}
		}
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}



//
//  FUNKTION: MyRegisterClass()
//
//  ZWECK: Registriert die Fensterklasse.
//
//  KOMMENTAR:
//
//    Sie müssen die Funktion zu verwenden, wenn Sie möchten, dass der Code
//    mit Win32-Systemen kompatibel ist, bevor die Funktion 'RegisterClassEx'
//    zu Windows 95 hinzugefügt wurde. Der Aufrud der Funktion ist wichtig,
//    damit die kleinen Symbole, die mit der Anwendung verknüpft sind,
//    richtig formatiert werden.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX); 

	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_LOC);
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCTSTR)IDC_LOC;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

	return RegisterClassEx(&wcex);
}

//
//   FUNKTION: InitInstance(HANDLE, int)
//
//   ZWECK: Speichert das Instanzenhandle und erstellt das Hauptfenster.
//
//   KOMMENTAR:
//
//        In dieser Funktion wird das Instanzenhandle in einer globalen Variablen gespeichert, und das
//        Hauptprogrammfenster wird erstellt und angezeigt.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
	HWND		hWnd;
	DWORD		style;				// holds popup flag, if needed
	DWORD		exStyle;			// extended style settings
	RECT		wndRect;
	DEVMODE		dmScreenSettings;

	hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern

	if (fullScreen) {
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
		dmScreenSettings.dmSize			= sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth	= fsWidth;				// Selected Screen Width
		dmScreenSettings.dmPelsHeight	= fsHeight;				// Selected Screen Height
		dmScreenSettings.dmBitsPerPel	= colDepth;				// Selected Bits Per Pixel
		dmScreenSettings.dmFields		= DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) {
			fullScreen = false;
		}
	}

	if (fullScreen) {
		exStyle=WS_EX_APPWINDOW;						// Window Extended Style
		style=WS_POPUP;									// Windows Style
		ShowCursor(FALSE);								// Hide Mouse Pointer
		wndRect.left=(long)0;
		wndRect.right=(long)width;
		wndRect.top=(long)0;
		wndRect.bottom=(long)height;
	} else {
		exStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;		// Window Extended Style
		style=WS_OVERLAPPEDWINDOW;						// Windows Style
		wndRect.left=(long)left;
		wndRect.right=(long)(left+width);
		wndRect.top=(long)top;
		wndRect.bottom=(long)(top+height);
	}

	AdjustWindowRectEx(&wndRect, style, FALSE, exStyle);

	hWnd = CreateWindowEx(exStyle,	// extended style
			szWindowClass,			// style class name
			szTitle,				// app name
			style | WS_VISIBLE | WS_SYSMENU,
									// window style
			wndRect.left, wndRect.top,
									// position
			width, height,			// size
			NULL,					// handle to Parent
			NULL,					// handle to menu
			hInstance,				// app instance handle
			NULL);					// no extra params

	if (!hWnd) {
		return FALSE;
	}

	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	return TRUE;
}



//
//  FUNKTION: SetupPixelFormat()
//
//  ZWECK:  Setzt das Pixelformat für den DC.
//
void SetupPixelFormat()
{
	int PixelFormat;
    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        colDepth,
        0,0,0,0,0,0,
        0,0,
        0,0,0,0,0,
        32,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0,0,
    };
    PixelFormat = ChoosePixelFormat(hDC, &pfd);
	if (!PixelFormat) MessageBox(NULL, "ChoosePixelFormat(hDC, &pfd) failed", "Error", NULL);
    SetPixelFormat(hDC, PixelFormat, &pfd);
}


//
// FUNKTION: ChangeDisplayMode
//
// ZWECK: Schaltet zwischen Full Screen und nomalem Modus hin und her.
//
bool ChangeDisplayMode(HWND hWnd)
{
	if (fullScreen) {	// toggle back to normal mode
		if (ChangeDisplaySettings(NULL,0) != DISP_CHANGE_SUCCESSFUL)
			return false;
		if (!SetWindowLong(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU))
			return false;
		//MoveWindow(hWnd, 100, 100, width, height, false);
		fullScreen = false;
		return true;
	}

	MoveWindow(hWnd, 0, 0, fsWidth, fsHeight, false);
	if (!SetWindowLong(hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE | WS_SYSMENU))
		return false;

	DEVMODE dev_mode = {0};
	LONG result;

	// get current dev_mode:
	if(!EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dev_mode))
		return false;

	// set what we need:
	dev_mode.dmPelsWidth	= fsWidth;				// Selected Screen Width
	dev_mode.dmPelsHeight	= fsHeight;				// Selected Screen Height
	dev_mode.dmBitsPerPel	= colDepth;					// Selected Bits Per Pixel
	dev_mode.dmFields		= DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
	
	// Now we'll try to change to full screen
	result = ChangeDisplaySettings(&dev_mode,CDS_FULLSCREEN);

	// ChangeDisplaySettings() returns DISP_CHANGE_SUCCESSFUL when it's successful
	if(result == DISP_CHANGE_SUCCESSFUL) {
		fullScreen = true;
		return true;	// success
	} else {
		fullScreen = false;
		return false;	// somethings wrong
	}
}
