#include "glstuff.h"


ascreenmode screen_mode;
//make window etc
HDC			hDC;
HGLRC		hRC;
HWND			hWnd;
HINSTANCE	hInstance;

extern atexture		*texture[MAX_TEXTURES];
GLfloat			LightAmbient[]= { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat			LightDiffuse[]= { 0.9f, 0.9f, 0.9f, 1.0f };
GLfloat			LightPosition[]= {0.0f, -6.0f, 4.0f, 1.0f };



int	vidrestart(void)
{
	int res=false;

	killglwindow();
	console("--old window killed--");

	res=createglwindow();
	console("--created new gl window--");
	

	if (res==1)//true
		console("--video restarted at %dx%d--",screen_mode.width,screen_mode.height);
	else
	{
		console("^1video restart failed at %dx%d",screen_mode.width,screen_mode.height);
		return false;
	}
	
	console("%s %s",glGetString(GL_VENDOR),glGetString(GL_RENDERER));////glGetString(GL_VERSION)

	//reload textures
	
	for (int i=0;i<MAX_TEXTURES;i++)
		if (texture[i]!=NULL)
		{
			/*
			//Sleep(1000);
			console("reloading texture #%d",i);
			//loadtex(texture[i]);
			if (!loadtex(texture[i]))
				console("^^***failed***");
				//return false;
			*/
			loadtex(texture[i]);

		}
/*	int oneDpos=0;
	findtexture("1d",&oneDpos);
	atexturedata *textureimage;
	textureimage=loadtexturefromfile("1d.tga");
	if (textureimage!=NULL)
	{
		glGenTextures(1,&texture[oneDpos]->data);

		glBindTexture(GL_TEXTURE_1D, texture[oneDpos]->data);
		glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		glTexImage1D(GL_TEXTURE_1D, 0, textureimage->type, 32,0,textureimage->type,GL_UNSIGNED_BYTE, textureimage->data);

		if (textureimage->data)
			free(textureimage->data);
		free(textureimage);
	}
*/

//	return (InitGL());
	return true;
}


PFNGLMULTITEXCOORD1FARBPROC	glMultiTexCoord1fARB	= NULL;
PFNGLMULTITEXCOORD2FARBPROC	glMultiTexCoord2fARB	= NULL;
PFNGLMULTITEXCOORD3FARBPROC	glMultiTexCoord3fARB	= NULL;
PFNGLMULTITEXCOORD4FARBPROC	glMultiTexCoord4fARB	= NULL;
PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB	= NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC	glClientActiveTextureARB= NULL;

#define __ARB_ENABLE true							// Used To Disable ARB Extensions Entirely
// #define EXT_INFO								// Uncomment To See Your Extensions At Start-Up?
#define MAX_EXTENSION_SPACE 10240						// Characters For Extension-Strings
#define MAX_EXTENSION_LENGTH 256						// Maximum Characters In One Extension-String
bool multitextureSupported=false;						// Flag Indicating Whether Multitexturing Is Supported
bool useMultitexture=true;							// Use It If It Is Supported?
GLint maxTexelUnits=1;

bool isInString(char *string, const char *search) {
	int pos=0;
	int maxpos=strlen(search)-1;
	int len=strlen(string);
	char *other;
	for (int i=0; i<len; i++) {
		if ((i==0) || ((i>1) && string[i-1]=='\n')) {			// New Extension Begins Here!
			other=&string[i];
			pos=0;							// Begin New Search
			while (string[i]!='\n') {				// Search Whole Extension-String
				if (string[i]==search[pos]) pos++;		// Next Position
				if ((pos>maxpos) && string[i+1]=='\n') return true;	// We Have A Winner!
				i++;
			}
		}
	}
	return false;								// Sorry, Not Found!
}

bool initMultitexture(void) {
	char *extensions;
	extensions=strdup((char *) glGetString(GL_EXTENSIONS));			// Fetch Extension String
	int len=strlen(extensions);
	for (int i=0; i<len; i++)						// Separate It By Newline Instead Of Blank
		if (extensions[i]==' ') extensions[i]='\n';

#ifdef EXT_INFO
	MessageBox(hWnd,extensions,"supported GL extensions",MB_OK | MB_ICONINFORMATION);
#endif

	if (isInString(extensions,"GL_ARB_multitexture")			// Is Multitexturing Supported?
		&& __ARB_ENABLE							// Override Flag
		&& isInString(extensions,"GL_EXT_texture_env_combine"))		// texture-environment-combining supported?
	{       
		glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&maxTexelUnits);
		glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) wglGetProcAddress("glMultiTexCoord1fARB");
		glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) wglGetProcAddress("glMultiTexCoord2fARB");
		glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) wglGetProcAddress("glMultiTexCoord3fARB");
		glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) wglGetProcAddress("glMultiTexCoord4fARB");
		glActiveTextureARB   = (PFNGLACTIVETEXTUREARBPROC) wglGetProcAddress("glActiveTextureARB");
		glClientActiveTextureARB= (PFNGLCLIENTACTIVETEXTUREARBPROC) wglGetProcAddress("glClientActiveTextureARB");
               
#ifdef EXT_INFO
		MessageBox(hWnd,"The GL_ARB_multitexture extension will be used.","feature supported!",MB_OK | MB_ICONINFORMATION);
#endif

		return true;
	}
	useMultitexture=false;							// We Can't Use It If It Isn't Supported!
	return false;
}



int initgl(void)										// All Setup For OpenGL Goes Here
{
	/*
	glShadeModel(GL_FLAT);
	glShadeModel(GL_SMOOTH);

	glClearColor(0.1f, 0.4f, 0.6f, 0.5f);				// Black Background
	glClearDepth(1.0f);									// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);							// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);								// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Really Nice Perspective Calculations

	//general light
	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	glEnable(GL_LIGHT1);

	//sun light
//	glLightfv(GL_LIGHT2, GL_DIFFUSE, SunLightDiffuse);
//	glLightfv(GL_LIGHT2, GL_POSITION,SunLightPosition);
//	glEnable(GL_LIGHT2);


//  glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
//  glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
//  glEnable(GL_TEXTURE_GEN_S);
//  glEnable(GL_TEXTURE_GEN_T);
	

//	glTexObject(GL_TEXTURE_CUBE_MAP_ARB);

	glMatrixMode( GL_MODELVIEW );
	//glLoadIdentity();

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_DEPTH_TEST);
	//glEnable(GL_CULL_FACE);
	//glCullFace(GL_FRONT);


	return TRUE;										// Initialization Went OK

*/
	multitextureSupported=initMultitexture();
	if (multitextureSupported)
		console("multiple textures extension supported");
	//general light
	//glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);
	glEnable(GL_LIGHT1);

	glEnable(GL_TEXTURE_2D);						// Enable Texture Mapping ( NEW )
	glShadeModel(GL_SMOOTH);						// Enable Smooth Shading
//	glShadeModel(GL_FLAT);
	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);					// Black Background
	glClearColor(0.1f, 0.4f, 0.6f, 0.5f);				// Black Background
	//glClearColor(1.0f, 1.0f, 1.0f, 0.5f);				// Black Background
	glClearDepth(1.0f);							// Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);						// Enables Depth Testing
	glDepthFunc(GL_LEQUAL);							// The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);			// Really Nice Perspective Calculations
	glEnable(GL_LIGHTING);
	
	glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);



	return TRUE;	
}


int createglwindow(void)
{
	GLuint		PixelFormat;
	WNDCLASS	wc;
	DWORD		dwExStyle;
	DWORD		dwStyle;
	RECT		WindowRect;
	
	WindowRect.left=(long)0;
	WindowRect.right=(long)screen_mode.width;
	WindowRect.top=(long)0;
	WindowRect.bottom=(long)screen_mode.height;


	hInstance			= GetModuleHandle(NULL);
	wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc		= (WNDPROC) WndProc;
	wc.cbClsExtra		= 0;									// No Extra Window Data
	wc.cbWndExtra		= 0;									// No Extra Window Data
	wc.hInstance		= hInstance;
	wc.hIcon			= LoadIcon(NULL, IDI_WINLOGO);			// Load The Default Icon
	wc.hCursor			= LoadCursor(NULL, IDC_ARROW);			// Load The Arrow Pointer
	wc.hbrBackground	= NULL;
	wc.lpszMenuName		= NULL;
	wc.lpszClassName	= "OpenGL";

	if (!RegisterClass(&wc))
	{
		console("^1failed to register window class");
		return false;
	}

	dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;			// Window Extended Style
	dwStyle=WS_OVERLAPPEDWINDOW;							// Windows Style
	
	if (screen_mode.fullscreen)
	{
		DEVMODE dmScreenSettings;
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));	// Makes Sure Memory's Cleared
		dmScreenSettings.dmSize=sizeof(dmScreenSettings);		// Size Of The Devmode Structure
		dmScreenSettings.dmPelsWidth	= screen_mode.width;				// Selected Screen Width
		dmScreenSettings.dmPelsHeight	= screen_mode.height;				// Selected Screen Height
		dmScreenSettings.dmBitsPerPel	= screen_mode.bpp;					// 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)
		{
			console("^1fullscreen mode not supported");
			return false;
		}
		dwExStyle=WS_EX_APPWINDOW;
		dwStyle=WS_POPUP;
		ShowCursor(FALSE);

	}

	dwExStyle=dwStyle=0;

	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

	// Create The Window -0,0 <-- pos
	if (!(hWnd=CreateWindowEx(dwExStyle,"OpenGL","gremd3",dwStyle|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
			0,0,WindowRect.right-WindowRect.left,WindowRect.bottom-WindowRect.top,NULL,NULL,hInstance,NULL)))
	{
		killglwindow();
		console("^1could not create window");
		return false;
	}

	static	PIXELFORMATDESCRIPTOR pfd=				// pfd Tells Windows How We Want Things To Be
	{
		sizeof(PIXELFORMATDESCRIPTOR),				// Size Of This Pixel Format Descriptor
		1,											// Version Number
		PFD_DRAW_TO_WINDOW |						// Format Must Support Window
		PFD_SUPPORT_OPENGL |						// Format Must Support OpenGL
		PFD_DOUBLEBUFFER,							// Must Support Double Buffering
		PFD_TYPE_RGBA,								// Request An RGBA Format
		screen_mode.bpp,										// Select Our Color Depth
		0, 0, 0, 0, 0, 0,							// Color Bits Ignored
		0,											// No Alpha Buffer
		0,											// Shift Bit Ignored
		0,											// No Accumulation Buffer
		0, 0, 0, 0,									// Accumulation Bits Ignored
		16,											// 16Bit Z-Buffer (Depth Buffer)  
		0,											// No Stencil Buffer
		0,											// No Auxiliary Buffer
		PFD_MAIN_PLANE,								// Main Drawing Layer
		0,											// Reserved
		0, 0, 0										// Layer Masks Ignored
	};
	
	if (!(hDC=GetDC(hWnd)))
	{
		killglwindow();
		console("^1cannot create DC");
		return false;
	}

	if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
	{
		killglwindow();
		console("^1cannot make a suitable pixelformat");
		return false;
	}

	if(!SetPixelFormat(hDC,PixelFormat,&pfd))
	{
		killglwindow();
		console("^1cannot set pixelformat");
		return false;
	}

	if (!(hRC=wglCreateContext(hDC)))
	{
		killglwindow();
		console("^1cannot create gl rendering context");
		return false;
	}

	if(!wglMakeCurrent(hDC,hRC))
	{
		killglwindow();
		console("^1cannot activate gl rendering context");
		return false;
	}

	ShowWindow(hWnd,SW_SHOW);
	SetForegroundWindow(hWnd);
	SetFocus(hWnd);

//	ReSizeGLScene(width, height); below
	if (screen_mode.height==0)										// Prevent A Divide By Zero By
	{
		screen_mode.height=1;										// Making Height Equal One
	}

	glViewport(0,0,screen_mode.width,screen_mode.height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f,(GLfloat)screen_mode.width/(GLfloat)screen_mode.height,0.1f,100.0f);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();	

	if (!initgl())
	{
		killglwindow();
		console("^1cannot init opengl");
		return false;
	}

	return true;
}

int killglwindow(void)
{
	if (screen_mode.fullscreen)										// Are We In Fullscreen Mode?
	{
		ChangeDisplaySettings(NULL,0);
	//ShowCursor(TRUE);	
	}

	ShowCursor(TRUE);

	if (hRC)
	{
		if (!wglMakeCurrent(NULL,NULL))
		{
			console("^1Release Of DC And RC Failed");
			return false;
		}

		if (!wglDeleteContext(hRC))
		{
			console("^1Release Rendering Context Failed");
			return false;
		}
		hRC=NULL;
	}

	if (hDC && !ReleaseDC(hWnd,hDC))
	{
		console("^1Release Device Context Failed");
		hDC=NULL;
		return false;
	}

	if (hWnd && !DestroyWindow(hWnd))
	{
		console("^1Could Not Release hWnd");
		hWnd=NULL;
		return false;
	}

	if (!UnregisterClass("OpenGL",hInstance))
	{
		console("^1Could Not Unregister Class");
		hInstance=NULL;
		return false;
	}


	return true;
}
