#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib,"glew32.lib")

char *VertexShaderSource,*FragmentShaderSource;

int VertexShader,FragmentShader;

int ShaderProgram;

GLfloat angle = 0.0;

char *readShaderFile(char *FileName) {
	FILE *fp;
	char *DATA = NULL;

	int flength = 0;

	fp = fopen(FileName,"rt");

    fseek(fp, 0, SEEK_END);
    flength = ftell(fp);
    rewind(fp);

	DATA = (char *)malloc(sizeof(char) * (flength+1));
	flength = fread(DATA, sizeof(char), flength, fp);
	DATA[flength] = '\0';
		
	fclose(fp);	

	return DATA;
}

void display (void) {
	glClearColor (0.0,0.0,0.0,1.0);
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();  
	glTranslatef(0,0,-5);
	glRotatef(angle,1,1,1);
	glUseProgramObjectARB(ShaderProgram);
	glColor3f(1,0,0);
	glutSolidCube(2);
	glutSwapBuffers();
	angle++;
}

void InitShader (void) {
	GLEW_ARB_vertex_shader;
	GLEW_ARB_fragment_shader;

	VertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
	FragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

	VertexShaderSource = readShaderFile("setup.vert");
	FragmentShaderSource = readShaderFile("setup.frag");

	const char * VS = VertexShaderSource;
	const char * FS = FragmentShaderSource;

	glShaderSourceARB(VertexShader, 1, &VS,NULL);
	glShaderSourceARB(FragmentShader, 1, &FS,NULL);
		
	free(VertexShaderSource);free(FragmentShaderSource);
		
	glCompileShaderARB(VertexShader);
	glCompileShaderARB(FragmentShader);
		
	ShaderProgram = glCreateProgramObjectARB();
			
	glAttachObjectARB(ShaderProgram,VertexShader);
	glAttachObjectARB(ShaderProgram,FragmentShader);

	glLinkProgramARB(ShaderProgram);
}

void DeInitShader (void) {
	glDetachObjectARB(ShaderProgram,VertexShader);
	glDetachObjectARB(ShaderProgram,FragmentShader);

	glDeleteObjectARB(ShaderProgram);
}

void Init (void) {
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
}

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

int main (int argc, char **argv) {
    glutInit (&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize (500, 500);
	glutInitWindowPosition (100, 100);
    glutCreateWindow ("A basic OpenGL Window");
	glewInit();
	InitShader();
	Init();
    glutDisplayFunc (display);
	glutIdleFunc (display);
	glutReshapeFunc (reshape);
    glutMainLoop ();
	DeInitShader();
    return 0;
}