/* 
 * This file is automaticaly generated, Please dont edit this file! 
 */
#include <opengl.h> 


































static int DoubleBufferAttributes[] = {
	GLX_RGBA,
	GLX_RED_SIZE, 1,
	GLX_GREEN_SIZE, 1,
	GLX_BLUE_SIZE, 1,
	GLX_DEPTH_SIZE, 12,
	GLX_DOUBLEBUFFER,
	None,
}; 



























void opengl_initialize( opengl * this ) {

		opengl_setupWindow( this );

		opengl_showVersion( this );

		opengl_createShaders( this );

		opengl_createQuad( this );

		

		opengl_setupTime( this );

		opengl_setupRenderLoop( this );

	}

void opengl_showVersion( opengl * this ) {

		printf("opengl version : %s\n\n", glGetString(GL_VERSION) );

	}

void opengl_setupTime( opengl * this ) {

		clock_gettime( CLOCK_REALTIME, &this->startTime );

	}

void opengl_setupWindow( opengl * this ) {

		this->mainDisplay			= XOpenDisplay( 0 );

		this->MainScreen			= XDefaultScreen( this->mainDisplay );

		this->RootWindow			= XDefaultRootWindow( this->mainDisplay );


		int empty;

		int ResultStatus			= glXQueryExtension( this->mainDisplay, &empty, &empty );

		XVisualInfo* VisualInfo		= glXChooseVisual( this->mainDisplay, this->MainScreen, DoubleBufferAttributes );

		GLXContext ShareList		= None;

		int IsDirectRendering		= True;

		GLXContext OpenGLContext	= glXCreateContext( this->mainDisplay, VisualInfo, ShareList, IsDirectRendering );



		int WindowX 			= 0;

		int WindowY 			= 0;

		int WindowWidth 		= 800;

		int WindowHeight 		= 600;

		int BorderWidth 		= 0;

		int WindowClass 		= InputOutput;

		int WindowDepth 		= VisualInfo->depth;


		Visual* WindowVisual 	= VisualInfo->visual;

		int AttributeValueMask 	= CWBackPixel | CWEventMask | CWColormap;


		XSetWindowAttributes WindowAttributes 	= {};

		WindowAttributes.colormap 				= XCreateColormap( this->mainDisplay, this->RootWindow, VisualInfo->visual, AllocNone);

		WindowAttributes.background_pixel 		= 0xffafe9af;

		WindowAttributes.event_mask 			= StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask;

		this->mainWindow 						= XCreateWindow( this->mainDisplay, this->RootWindow, 
																WindowX, WindowY, WindowWidth, WindowHeight,
																BorderWidth, WindowDepth, WindowClass, WindowVisual,
																AttributeValueMask, &WindowAttributes);

		XStoreName( this->mainDisplay, this->mainWindow, "Opengl: Fixed function pipeline" );

		glXMakeCurrent( this->mainDisplay, this->mainWindow, OpenGLContext );

		XMapWindow( this->mainDisplay, this->mainWindow );

		Atom WM_DELETE_WINDOW 			= XInternAtom( this->mainDisplay, "WM_DELETE_WINDOW", False );

		if( !XSetWMProtocols( this->mainDisplay, this->mainWindow, &WM_DELETE_WINDOW, 1) ) {

		    printf( "Couldn't register WM_DELETE_WINDOW\n" );

		}

	}

void opengl_setupRenderLoop( opengl * this ) {

		int IsProgramRunning 	= 1;

		while( IsProgramRunning ) {

		    while( XPending( this->mainDisplay ) ) {

		        XEvent GeneralEvent = {};

		        XNextEvent( this->mainDisplay, &GeneralEvent );

		        switch( GeneralEvent.type ) {

		            case ClientMessage: 
		            {

		                IsProgramRunning = 0;

		            } break;
		        }

		    }

		    {

		    	opengl_render( this );

		    }
		    
		}

	}

void opengl_createShaders( opengl * this ) {


		shader * currentShader = shader_newPointer();


		shader_createFromFile( currentShader,  "assets/shaders/color.vertex", "assets/shaders/color.fragment" );

		vector3 * diffuseColor	= vector3_newPointer( 0.0, 1.0, 0.0 );

		shader_setUniform( currentShader,  "diffuse", diffuseColor );

		vector2 * position	= vector2_newPointer( 1.0, 0.0 );

		shader_setUniform( currentShader,  "position", position );

		this->currentShader = currentShader;

	}

void opengl_createQuad( opengl * this ) {

		this->quads = mesh_newPointer();

		mesh_createBuffers( this->quads );


	}

double opengl_clockToMilliseconds( opengl * this, clock_t ticks ) {

		return ( ticks / ( double ) CLOCKS_PER_SEC );

	}

void opengl_render( opengl * this ) {

		

		Window qRoot;

		Window qChild;

		unsigned int qMask;

		int childX;

		int childY;

		int mouseX;

		int mouseY;

		int child;

		

		int windowX			= 0;

		int windowY			= 0;

		int windowWidth		= 0;

		int windowHeight	= 0;




		XWindowAttributes window;

		

		if( XGetWindowAttributes( this->mainDisplay, this->mainWindow, &window ) ) {

			

			

















































		}



		if( XQueryPointer( this->mainDisplay, this->RootWindow, &qRoot, &qChild, &mouseX, &mouseY, &childX, &childY, &qMask ) )
		{

			mouseX -= window.x;

			mouseY -= window.y;

			for(int i = 0; i < sizeof(int) * 8; i++)
			{
				int mask = 1 << sizeof(int) * 8 - i - 1;

				if(mask & qMask)
				{
					
				}
				else
				{
					
				}

			}

			

			if( qMask == Button1MotionMask ) {

				printf("LeftMouse\n");

			}


			if( qMask == Button2MotionMask ) {

				printf("Button2MotionMask\n");
				
			}


			if( qMask == Button3MotionMask ) {

				printf("RightMouse\n");
				
			}

			if( qMask == Button4MotionMask ) {

				printf("Button2MotionMask\n");
				
			}


			if( qMask == Button5MotionMask ) {

				printf("Button2MotionMask\n");
				
			}

			if( qMask == ShiftMask ) {

				printf("Pressed shift\n");
				
			}

			if( qMask == ControlMask ) {

				printf("Pressed control\n");
				
			}


			if( qMask == EnterWindowMask ) {

				
				
			}



			XEvent   event;

			int keyboardEventCount	=  XPending( this->mainDisplay );

			

			while( XPending( this->mainDisplay ) ) {


				XNextEvent( this->mainDisplay, &event );

				switch ( event.type ) {

					case KeyPress:

						printf("key has been pressed.  %i\n\n", event.xkey.keycode);

					break;


					case KeyRelease:

						printf("key has been released.  %i\n\n", event.xkey.keycode);

					break;


					

					case Expose:

					break;



					default:

						

						

				}

				

			}



			

			

			


			

		}





		opengl_clearColor( this,  0.0, 1.0, 0.6, 1.0 );

		opengl_clear( this,  GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

		

		float number = (float)(this->frameCount & 1000) / 1000;

			shader * currentShader 			= this->currentShader;

			
			

			

			vector2 * windowSize = vector2_newPointer( window.width, window.height );

			vector2 * mouse = vector2_newPointer( mouseX, mouseY );

			shader_setUniform( currentShader,  "window", windowSize );

			shader_setUniform( currentShader,  "mouse", mouse );

			int itemSize;


			glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

			glEnableVertexAttribArray( 0 );

			glEnableVertexAttribArray( 1 );

			glEnableVertexAttribArray( 3 );




			itemSize	= 3;

			glBindBuffer( GL_ARRAY_BUFFER, this->quads->vertexbuffer );

			glVertexAttribPointer( 0, itemSize, GL_FLOAT, GL_FALSE, 0, ( void * ) 0 );


			itemSize	= 2;

			glBindBuffer( GL_ARRAY_BUFFER, this->quads->textureCoordinateBuffer );

			glVertexAttribPointer( 1, itemSize, GL_FLOAT, GL_FALSE, 0, ( void * ) 0 );


			itemSize	= 1;

			glBindBuffer( GL_ARRAY_BUFFER, this->quads->meshIndexBuffer );

			glVertexAttribPointer( 2, itemSize, GL_FLOAT, GL_FALSE, 0, ( void * ) 0 );


			int numItems	= 10000;

			glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, this->quads->indexBuffer );

			glDrawElements( GL_TRIANGLES, numItems, GL_UNSIGNED_INT, ( void * ) 0 ); 

			glDisableVertexAttribArray( 0 );

			glDisableVertexAttribArray( 1 );



		opengl_end( this );

		opengl_flush( this );

		

	}

void opengl_displayFPS( opengl * this ) {

		struct timespec 	now;

		clock_gettime( CLOCK_REALTIME, &now );

		this->frameCount++;

		int elapsedTime		= now.tv_sec - this->startTime.tv_sec;
    	
		if( elapsedTime != this->lastTime ) {

			printf("%i fps.\n\n",  this->frameCount  );
			
			this->lastTime = elapsedTime;

			this->frameCount = 0;

		}

	}

void opengl_vertex2f( opengl * this, float x,  float y ) {

		glVertex2f( x, y );

	}

void opengl_color3f( opengl * this, float r,  float g,  float b ) {

		glColor3f( r, g, b );

	}

void opengl_clear( opengl * this, GLbitfield mask ) {

		 glClear( mask );

	}

void opengl_clearColor( opengl * this, float r,  float g,  float b,  float a ) {

		glClearColor( r, g, b, a );

	}

void opengl_begin( opengl * this, GLenum mode ) {

		glBegin( mode );

	}

void opengl_end( opengl * this ) {

		glEnd();

	}

void opengl_flush( opengl * this ) {

		

		

		

		PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
		PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA;
		PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;

		glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalEXT");

		if (glXSwapIntervalEXT != NULL) {

			glXSwapIntervalEXT(this->mainDisplay, this->mainWindow, 0);

		} else {

			glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalMESA");

			

			if ( glXSwapIntervalMESA != NULL ) {

				glXSwapIntervalMESA(0);

			} else {

			glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress( (const GLubyte*)"glXSwapIntervalSGI");
			
			if ( glXSwapIntervalSGI != NULL ) {
				glXSwapIntervalSGI(0);
			}

			}
		}

		glXSwapBuffers( this->mainDisplay, this->mainWindow );
		


		

	}

opengl opengl_new() {

	opengl instance;

	instance.__classIndex = 0;

	instance.lastTime =  clock();

	instance.deltaTime =  0;

	instance.frameCount =  0;

	return instance;

}

opengl * opengl_newPointer() {

	struct opengl * pointer = malloc( sizeof ( struct opengl ) );

	pointer->__classIndex = 0;

	pointer->lastTime =  clock();

	pointer->deltaTime =  0;

	pointer->frameCount =  0;

	return pointer;

}

