#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <unistd.h>
#include <math.h>

GLuint texture;
GLfloat angle = 0.0;
float Mouse_X = 0;
float Mouse_Y = 0;

GLuint LoadTexture( const char * filename, int width, int height ){
	GLuint texture;
	unsigned char * data;
	FILE * file;
	file = fopen( filename, "rb" );
	if ( file == NULL ) return 0;
	int header_size = 0;
	data = (unsigned char *)malloc( width * height * 3 );
	fseek ( file , 54 , SEEK_SET );

	fread( data, width * height * 3, 1, file );
	fclose( file );
	glGenTextures( 1, &texture );
	glBindTexture( GL_TEXTURE_2D, texture );
	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

	//The qualities are (in order from worst to best)
	//GL_NEAREST
	//GL_LINEAR
	//GL_LINEAR_MIPMAP_NEAREST
	//GL_LINEAR_MIPMAP_LINEAR

	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
	free( data );
	return texture;
}

void FreeTexture( GLuint texture )
{
	glDeleteTextures( 1, &texture );
}

void square (void) {
    glBindTexture( GL_TEXTURE_2D, texture ); //bind our texture
    glRotatef( angle, 1.0f, 1.0f, 1.0f );

    glBegin (GL_QUADS);
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0); //with 
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0); //so that
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
    glEnd();


/*
    glBegin (GL_QUADS);
    glTexCoord2d(1.0,1.0); glVertex2d(-0.5,-0.5); //with
    glTexCoord2d(2.0,1.0); glVertex2d(+0.5,-0.5); //so that
    glTexCoord2d(2.0,2.0); glVertex2d(+0.5,+0.5);
    glTexCoord2d(1.0,2.0); glVertex2d(-0.5,+0.5);
    glEnd();
*/



//This is how texture coordinates are arranged
//
//  0,1   ---   1,1
//       |     |
//       |     |
//       |     |
//  0,0   ---   1,0

}

void display (void) {
    glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glEnable( GL_TEXTURE_2D );

    gluLookAt ( (Mouse_X-250)/500, 0.0, 5.0, 0.0, (Mouse_Y-250)/500, 0.0, 0.0, 1.0, 0.0);

    square();
/*
	Display *dpy = XOpenDisplay(NULL);
	int CursorX=0;
	int CursorY=0;
	XEvent newEvent;
	XNextEvent(dpy, &newEvent);
	if(newEvent.type == MotionNotify){
		CursorX = newEvent.xmotion.x;
		CursorY = newEvent.xmotion.y;
	}
	printf("x: %d y: %d\n", CursorX, CursorY);
*/

    glutSwapBuffers();
	//    angle ++;
}


void reshape (int w, int h) {
    glViewport (0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective (60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode (GL_MODELVIEW);
}


void mouse_active (int x,int y){
	//printf("a - x: %d y: %d\n", x, y);
	Mouse_X = x;
	Mouse_Y = y;
}

void mouse_passive (int x,int y){
        //printf("p - x: %d y: %d\n", x, y);
	Mouse_X = x;
	Mouse_Y = y;
}




int main (int argc, char **argv) {
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE);
    glutInitWindowSize (500, 500);
    glutInitWindowPosition (100, 100);
    glutCreateWindow ("A basic OpenGL Window");
    glutDisplayFunc (display);
    glutIdleFunc (display);
    glutReshapeFunc (reshape);
    glutMotionFunc(mouse_active);
    glutPassiveMotionFunc(mouse_passive); 

    //Load our texture
    texture = LoadTexture( "texture.raw", 256, 256 );

	printf("max texture coords: %d\n", GL_MAX_TEXTURE_COORDS);
	printf("max com tex img coords: %d\n", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);

    glutMainLoop ();

    //Free our texture
    FreeTexture( texture );

    return 0;
}
