#include <GL/glut.h>
#include <cmath>
#include <string>
#include <strstream>

#include "globale.h"
#include "CVector3.h"
#include "CCamera.h"
#include "Gameinput.h"
#include "CWinStream.h"

float Lumiere[] = {200, 200, 200, 1.0};
float couleur[] = {1.0, 1.0, 1.0, 1.0};


// Variable globale comme les define

const float SPEEDCAM = 0.02f;
short CENTRE_X;
short CENTRE_Y;

CCamera gCamera;
CWinStream wout;


float Hauteurs[DIV_X][DIV_Y];
float Vitesses[DIV_X][DIV_Y];
CVector3 Normales[DIV_X][DIV_Y];

void display();
void InitVitesse();
void InitHauteur();


void init(void)
{
	glClearColor(0.0, 0.0, 0.0, 1.0);

	glutSetCursor(GLUT_CURSOR_NONE);

	gCamera.DisplayFunc = display;

	GLfloat exposant = 50.0;

	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
	
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &exposant);
		
	glLightfv(GL_LIGHT0, GL_AMBIENT, couleur);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, couleur);
	glLightfv(GL_LIGHT0, GL_SPECULAR, couleur);
		
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	glEnable(GL_DEPTH_TEST);

	glShadeModel(GL_SMOOTH);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glEnable(GL_POINT_SMOOTH);
	glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

	glDepthMask(GL_TRUE);

	InitHauteur();
	InitVitesse();

	CENTRE_X = glutGet(GLUT_WINDOW_WIDTH) >> 1;
	CENTRE_Y = glutGet(GLUT_WINDOW_HEIGHT) >> 1;

	glutWarpPointer(CENTRE_X, CENTRE_Y);
}




void Cartesien(void)
{
	GLfloat x[] = {1.0, 0.0, 0.0, 1.0};
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, x);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, x);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, x);
	glColor4fv(x);
	glLineWidth(4.0);
	glBegin(GL_LINES);
		glVertex3f(0.0, 0.0, 0.0);
		glVertex3f(4.0, 0.0, 0.0);
	glEnd();

	GLfloat y[] = {0.0, 1.0, 0.0, 1.0};
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, y);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, y);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, y);
	glColor4fv(y);
	glLineWidth(4.0);
	glBegin(GL_LINES);
		glVertex3f(0.0, 0.0, 0.0);
		glVertex3f(0.0, 4.0, 0.0);
	glEnd();

	GLfloat z[] = {0.0, 0.0, 1.0, 1.0};
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, z);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, z);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, z);
	glColor4fv(z);
	glLineWidth(4.0);
	glBegin(GL_LINES);
		glVertex3f(0.0, 0.0, 0.0);
		glVertex3f(0.0, 0.0, 4.0);
	glEnd();

	GLfloat nul[] = {0.0, 0.0, 0.0, 1.0};
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, nul);
}

void CalculHauteur();

#include "Temps.h"
inline void FPS(void)
{
	static long Temps = GetTemps();
	static int Compteur = 0;
	static int AncienCompteur = 0;

	++Compteur;

	if (GetTemps() - Temps > 1000)
	{
		Temps = GetTemps();
		AncienCompteur = Compteur;
		Compteur = 0;
	}

	glDisable(GL_LIGHTING);
	wout.Begin();
	wout.SetCouleur(1,1,1,1);
	wout.SetPos(10, 10);	
	wout << AncienCompteur;
	wout.End();
	glEnable(GL_LIGHTING);
	
}

void display(void)
{
	static int Compteur = 0;

	CalculHauteur();

	Compteur++;

	if (Compteur >= CALCULPARFRAME)
	{
		Compteur = 0;

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gCamera.CamLookAt();

		float Toile[] = {0.7, 0.7, 0.7, 1.0};
		float ToileAm[] = {0.3, 0.3, 0.3, 1.0};
		float ToileSpec[] = {1.0, 1.0, 1.0, 1.0};
		glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, ToileSpec);
		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, Toile);
		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ToileAm);
		glColor3f(1.0, 1.0, 1.0);
		
		for (int i = 0; i < DIV_X-1; i++)
			for (int j = 0; j < DIV_Y-1; j++)
			{
				glBegin(GL_QUADS);
					glNormal3f(Normales[i][j].x,
							   Normales[i][j].y,
							   Normales[i][j].z);
					glVertex3f(-5.0f + i * 10.0f / float(DIV_X),
							 -5.0f + j * 10.0f / float(DIV_Y),
							 Hauteurs[i][j]*HAUTEURAMP);
					glNormal3f(Normales[i+1][j].x,
							   Normales[i+1][j].y,
							   Normales[i+1][j].z);
					glVertex3f(-5.0f + (i+1) * 10.0f / float(DIV_X),
							 -5.0f + j * 10.0f / float(DIV_Y),
							 Hauteurs[i+1][j]*HAUTEURAMP);
					glNormal3f(Normales[i+1][j+1].x,
							   Normales[i+1][j+1].y,
							   Normales[i+1][j+1].z);
					glVertex3f(-5.0f + (i+1) * 10.0f / float(DIV_X),
							 -5.0f + (j+1) * 10.0f / float(DIV_Y),
							 Hauteurs[i+1][j+1]*HAUTEURAMP);
					glNormal3f(Normales[i][j+1].x,
							   Normales[i][j+1].y,
							   Normales[i][j+1].z);
					glVertex3f(-5.0f + i * 10.0f / float(DIV_X),
							 -5.0f + (j+1) * 10.0f / float(DIV_Y),
							 Hauteurs[i][j+1]*HAUTEURAMP);
				glEnd();
			}

		Cartesien();
		
		glLightfv(GL_LIGHT0, GL_POSITION, Lumiere);

		FPS();
		glFinish();
		glutSwapBuffers();
	}
}

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

	CENTRE_X = w >> 1;
	CENTRE_Y = h >> 1;

	wout.SetToWindow();
}

void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
	case (27): exit(0); break;
	default: break;
	}
}

void Idle() { BougeSouris(CENTRE_X, CENTRE_Y); }


#include <iostream>
#include <cmath>

int main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
#ifndef FULLSCREEN
	glutInitWindowSize(500,500);
#else
	glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT));
#endif
	glutInitWindowPosition((glutGet(GLUT_SCREEN_WIDTH) - glutGet(GLUT_INIT_WINDOW_WIDTH)) >> 1,
						   (glutGet(GLUT_SCREEN_HEIGHT) - glutGet(GLUT_INIT_WINDOW_HEIGHT)) >> 1);
	glutCreateWindow("Ondes");
#ifdef FULLSCREEN
	glutFullScreen();
#endif
	init();
	glutDisplayFunc(display);
	glutIdleFunc(Idle);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMouseFunc(CliqueSouris);
	glutMotionFunc(BougeSouris);
	glutPassiveMotionFunc(BougeSouris);

	glutMainLoop();
	return 0;
}
