#include "project.h"

#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 4
#endif

bool wm_esc;
HDC  wm_hDC=NULL;
bool wm_fullscreen=false;

HWND         wm_hWnd=NULL;
HGLRC        wm_hRC=NULL;
HINSTANCE    wm_hInstance;

char* wm_ClassName = "OpenGLClass";

void wm_Kill()
{
	if (wm_fullscreen)
	{
		ChangeDisplaySettings(NULL,0);
		ShowCursor(true);
	}
	if (wm_hRC)
	{
		if (!wglMakeCurrent(NULL,NULL))
		{
			MessageBox(NULL,"DC and RC release failed.","Error",MB_OK);
		}

		if (!wglDeleteContext(wm_hRC))
		{
			MessageBox(NULL,"RC release failed.","Error",MB_OK);
		}
		wm_hRC=NULL;
	}
	if (wm_hDC && !ReleaseDC(wm_hWnd,wm_hDC))
	{
		MessageBox(NULL,"DC release failed.","Error",MB_OK);
		wm_hDC=NULL;
	}
	if (wm_hWnd && !DestroyWindow(wm_hWnd))
	{
		MessageBox(NULL,"Couldn't release hWnd.","Error",MB_OK);
		wm_hWnd=NULL;
	}
	if (!UnregisterClass(wm_ClassName,wm_hInstance))
	{
		MessageBox(NULL,"Couldn't unregister class.","Error",MB_OK);
		wm_hInstance=NULL;
	}
}

LRESULT CALLBACK WndProc(HWND par_hWnd, UINT uMsg, WPARAM par_wParam, LPARAM par_lParam)
{
	if (uMsg==WM_SYSCOMMAND)
	{
		switch (par_wParam)
		{
			case SC_SCREENSAVE:
			case SC_MONITORPOWER:
			return 0;
		}
	}
	switch (uMsg)
	{
		//case WM_ACTIVATE:	wm_active = (HIWORD(par_wParam))?(false):(true); return 0;
		case WM_CLOSE:			PostQuitMessage(0);
								return 0;

		case WM_KEYDOWN:		if (par_wParam==VK_ESCAPE) wm_esc = true; return 0;
		case WM_KEYUP:			if (par_wParam==VK_ESCAPE) wm_esc = false; return 0;
		case WM_LBUTTONDOWN: fprintf(f,"%d\n",GetSync); return 0;
	}
	return DefWindowProc(par_hWnd,uMsg,par_wParam,par_lParam);
}

bool wm_Init(int width, int height, byte bpp, bool fullscreen, char *title, float fov, float zNear, float zFar)
{
	wm_fullscreen=fullscreen;
	wm_esc=false;
	
   	GLuint		PixelFormat;
	WNDCLASS	wc;
	DWORD		dwExStyle;
	DWORD		dwStyle;
	RECT		WindowRect;

	WindowRect.left=(long)0;
	WindowRect.right=(long)width;
	WindowRect.top=(long)0;
	WindowRect.bottom=(long)height;

	wm_hInstance		= GetModuleHandle(NULL);

	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc		= (WNDPROC) WndProc;
	wc.cbClsExtra		= 0;
	wc.cbWndExtra		= 0;
	wc.hInstance		= wm_hInstance;
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground	= NULL;
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= wm_ClassName;

    if (!RegisterClass(&wc))
	{
		MessageBox(NULL,"Failed to register the window class.","Error",MB_OK);
		return false;
	}
	if (wm_fullscreen)
	{
		DEVMODE dmScreenSettings;
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
		dmScreenSettings.dmSize			= sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth	= width;
		dmScreenSettings.dmPelsHeight	= height;
 		dmScreenSettings.dmBitsPerPel	= bpp;
		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
		{
			if (MessageBox(NULL,"The requested wm_fullscreen mode is not supported by\nyour video card. Use windowed mode instead?","Mode error",MB_YESNO)==IDYES)
			{
				wm_fullscreen=false;
			}
			else
			{
				MessageBox(NULL,"Program will now close.","Error",MB_OK);
				return false;
			}
		}
	}
	if (wm_fullscreen)
	{
		dwExStyle=WS_EX_APPWINDOW;
		dwStyle=WS_POPUP;
		ShowCursor(false);
	}
	else
	{
		dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
		dwStyle=WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; /*WS_MINIMIZEBOX | WS_MAXIMIZEBOX*/ /*WS_OVERLAPPEDWINDOW*/
	}
	AdjustWindowRectEx(&WindowRect, dwStyle, false, dwExStyle);
	if (!(wm_hWnd=CreateWindowEx(
					dwExStyle,
					wm_ClassName,
					title,
					WS_CLIPSIBLINGS |
					WS_CLIPCHILDREN |
					dwStyle,
					0, 0,
					WindowRect.right-WindowRect.left,
					WindowRect.bottom-WindowRect.top,
					NULL,
					NULL,
					wm_hInstance,
					NULL)))
	{
		wm_Kill();
		MessageBox(NULL,"Window creation error.","Error",MB_OK);
		return false;
	}
	static PIXELFORMATDESCRIPTOR pfd=
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW |
		PFD_SUPPORT_OPENGL |
		PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		bpp,
		0, 0, 0, 0, 0, 0,
		0,
		0,
		0,
		0, 0, 0, 0,
		16,
		0,
		0,
		PFD_MAIN_PLANE,
		0,
		0, 0, 0
	};
	if (!(wm_hDC=GetDC(wm_hWnd)))
	{
		wm_Kill();
		MessageBox(NULL,"Can't create DC.","Error",MB_OK);
		return false;
	}
	if (!(PixelFormat=ChoosePixelFormat(wm_hDC,&pfd)))
	{
		wm_Kill();
		MessageBox(NULL,"Can't find a suitable PixelFormat.","Error",MB_OK);
		return false;
	}
	if(!SetPixelFormat(wm_hDC,PixelFormat,&pfd))
	{
		wm_Kill();
		MessageBox(NULL,"Can't Set The PixelFormat.","Error",MB_OK);
		return false;
	}
	if (!(wm_hRC=wglCreateContext(wm_hDC)))
	{
		wm_Kill();
		MessageBox(NULL,"Can't create RC.","Error",MB_OK);
		return false;
	}
	if(!wglMakeCurrent(wm_hDC,wm_hRC))
	{
		wm_Kill();
		MessageBox(NULL,"Can't activate the RC.","Error",MB_OK);
		return false;
	}
	ShowWindow(wm_hWnd,SW_SHOW);
	SetForegroundWindow(wm_hWnd);
	SetFocus(wm_hWnd);
	
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(fov,(float)width/(float)height,zNear,zFar);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();


	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	return true;
}
