//  
// Example code for OpenGL programming
//
#include <iostream>
#include <stdlib.h>
#include <GL/glut.h>
#include "tiling.c"

using namespace std;


int nFPS = 60;
float fRotateAngle = 0.f;

void init(void)
{
	// init your data, setup OpenGL environment here
	glClearColor(0.9,0.9,0.9,1.0); // clear color is gray		
	
					// GL_POINT / GL_LINE / GL_FILL (default)
	glPointSize(4.0);
	GLfloat white[] = {1.0,1.0,1.0,1.0};
	GLfloat lpos[] = {0.0,1.0,0.0,0.0};

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	glLightfv(GL_LIGHT0, GL_POSITION, lpos);
	glLightfv(GL_LIGHT0, GL_AMBIENT, white);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, white);
	glLightfv(GL_LIGHT0, GL_SPECULAR, white);

	glClearColor (1, 1, 1.0, 0.0);
	/* glShadeModel (GL_FLAT); */
	glEnable(GL_DEPTH_TEST);
		// setup look at transformation so that 
	// eye is at : (0,0,3)
	// look at center is at : (0,0,0)
	// up direction is +y axis
	gluLookAt(0.f,3.f,2.f,0.f,0.f,0.f,0.f,1.f,0.f);
}

void display(void)
{
	GLfloat tanamb[] = {0.2,0.15,0.1,1.0};
	GLfloat tandiff[] = {0.4,0.3,0.2,1.0};

	GLfloat seaamb[] = {0.0,0.0,0.2,1.0};
	GLfloat seadiff[] = {0.0,0.0,0.8,1.0};
	GLfloat seaspec[] = {0.5,0.5,1.0,1.0};


	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f (1.0, 1.0, 1.0);
	

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, tanamb);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, tandiff);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, tandiff);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0);

	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, seaamb);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, seadiff);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, seaspec);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0);

	// reset OpenGL transformation matrix
	glMatrixMode(GL_MODELVIEW);



	// Test drawing a solid teapot
	glColor3f(1.0,0.0,0.0); // set current color to Red
	//glutSolidTeapot(1.f); // call glut utility to draw a solid teapot 

	//texture
	GLuint image;

	glGenTextures(1,&image);
	gluBuild2DMipmaps(GL_TEXTURE_2D, gimp_image.bytes_per_pixel, gimp_image.width, gimp_image.height, GL_RGBA, GL_UNSIGNED_BYTE, gimp_image.pixel_data);
	glEnable(GL_TEXTURE_2D);

	glBegin(GL_TRIANGLE_STRIP);
		glNormal3f(0.0,0.0,-1.0);
		glVertex3f(0-1.5,0-.5,0);
		glVertex3f(.5-1.5,1-.5,0);
		glVertex3f(1-1.5,0-.5,0);
		glVertex3f(1.5-1.5,.8-.5,0);
		glVertex3f(2-1.5,0-.5,0);
		glVertex3f(3-1.5,1-.5,0);
	glEnd();
	glBegin(GL_QUADS);
		
		glNormal3f(-1.0,0.0,0.0);
		glVertex3f(0-1.5,0-.5,0);
		glVertex3f(.5-1.5,1-.5,0);
		glVertex3f(.5-1.5,1-.5,1);
		glVertex3f(0-1.5,0-.5,1);

		glNormal3f(0.0,1.0,0.0);
		glVertex3f(.5-1.5,1-.5,0);
		glVertex3f(1.5-1.5,.8-.5,0);
		glVertex3f(1.5-1.5,.8-.5,1);
		glVertex3f(.5-1.5,1-.5,1);
		
		//the rectangle with texture
		glNormal3f(0.0,1.0,0.0);
		glTexCoord2d(0.0,1.0);
		glVertex3f(1.5-1.5,.8-.5,0);
		glTexCoord2d(0.0,0.0);
		glVertex3f(1.5-1.5,.8-.5,1);
		glTexCoord2d(1.0,0.0);
		glVertex3f(3-1.5,1-.5,1);
		glTexCoord2d(1.0,1.0);
		glVertex3f(3-1.5,1-.5,0);

		glNormal3f(1.0,0.0,0.0);
		glVertex3f(3-1.5,1-.5,1);
		glVertex3f(3-1.5,1-.5,0);
		glVertex3f(2-1.5,0-.5,0);
		glVertex3f(2-1.5,0-.5,1);

		glNormal3f(0.0,-1.0,0.0);
		glVertex3f(2-1.5,0-.5,0);
		glVertex3f(2-1.5,0-.5,1);
		glVertex3f(0-1.5,0-.5,1);
		glVertex3f(0-1.5,0-.5,0);

	glEnd();
	glBegin(GL_TRIANGLE_STRIP);
		glNormal3f(0.0,0.0,1.0);
		glVertex3f(0-1.5,0-.5,1);
		glVertex3f(.5-1.5,1-.5,1);
		glVertex3f(1-1.5,0-.5,1);
		glVertex3f(1.5-1.5,.8-.5,1);
		glVertex3f(2-1.5,0-.5,1);
		glVertex3f(3-1.5,1-.5,1);
	glEnd();
	
	//glFlush();
	glutSwapBuffers();	// swap front/back framebuffer to avoid flickering 
}

void reshape (int w, int h)
{
	// reset viewport ( drawing screen ) size
	glViewport(0, 0, w, h);
	float fAspect = ((float)w)/h; 
	// reset OpenGL projection matrix
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(70.f,fAspect,0.001f,30.f); 
}



void keyboard(unsigned char key, int x, int y)
{
	// put your keyboard control here
	if (key == 27) 
	{
		// ESC hit, so quit
		printf("demonstration finished.\n");
		exit(0);
	}
	if(key=='w'||key=='W'){
		cout<<"w is pressed"<<endl;
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // uncomment this function if you only want to draw wireframe model
	}
	if(key=='f'||key=='F'){
		cout<<"f is pressed"<<endl;
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // uncomment this function if you only want to draw fill model
	}
	if(key=='p'||key=='P'){
		cout<<"new perspective"<<endl;
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(70.f,1,0.001f,30.f);
	}
	if(key=='o'||key=='O'){
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(-2,2,-2,2,0.001, 50);
	}
}

void mouse(int button, int state, int x, int y)
{
	// process your mouse control here
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
		printf("push left mouse button.\n");
}


void timer(int v)
{
	fRotateAngle += 1.f; // change rotation angles
	glutPostRedisplay(); // trigger display function by sending redraw into message queue
	glutTimerFunc(1000/nFPS,timer,v); // restart timer again
}

int main(int argc, char* argv[])
{
	glutInit(&argc, (char**)argv);
	// set up for double-buffering & RGB color buffer & depth test
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
	glutInitWindowSize (500, 500); 
	glutInitWindowPosition (100, 100);
	glutCreateWindow ((const char*)"Hello Triangle");

	init(); // setting up user data & OpenGL environment
	
	// set up the call-back functions 
	glutDisplayFunc(display);  // called when drawing 
	glutReshapeFunc(reshape);  // called when change window size
	glutKeyboardFunc(keyboard); // called when received keyboard interaction
	glutMouseFunc(mouse);	    // called when received mouse interaction
	glutTimerFunc(100,timer,nFPS); // a periodic timer. Usually used for updating animation
	
	glutMainLoop(); // start the main message-callback loop

	return 0;
}
