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

#include "globale.h"
#include "Temps.h"
#include "CVector3.h"
#include "CCamera.h"
#include "CCube.h"
#include "CBloc.h"
#include "CJeu.h"
#include "CWinStream.h"

#define DIVISION	20


void Plan(void)
{
	for (int i = - MAX_X ; i < 2 * MAX_X; i++)
		for (int j = - MAX_Y; j < 2 * MAX_Y; j++)
		{
			if ((i + j) % 2)
				// Couleur des carrées qui sont partout;
				glColor3f(0.8f, 0.8f, 0.8f);
			else if ( (i >= 0) && (i < MAX_X) && (j >= 0) && (j < MAX_Y) )
				// Couleur des carrées uniquement à l'intérieur
				glColor3f(0.3f, 0.0f, 0.0f);
			else
				// Couleur des carrées uniquement à l'extérieur
				glColor3f(0.0f, 0.0f, 0.3f);
			
			glBegin(GL_QUADS);
				glNormal3f(0.0, 0.0, 1.0);
				glVertex3f(i, j, 0);
				glVertex3f(i+1, j, 0);
				glVertex3f(i+1, j+1, 0);
				glVertex3f(i, j+1, 0);
			glEnd();
		}
}




void Boite(void)
{
	glColor4f(0.1, 0, 0.4, 0.5);

	int i, j;

	CVector3 UnVect;

	UnVect = gCamera.Position - CVector3(0, 0, 0);

	if (UnVect * CVector3(0, 1, 0) > 0)
	{
		// Plan y = 0
		for (i = 0; i < DIVISION; i++)
			for (j = 0; j < DIVISION; j++)
			{
				glBegin(GL_QUADS);
					glNormal3f(0.0, -1.0, 0.0);
					glVertex3f(i*MAX_X / DIVISION, 0, j * MAX_Z / DIVISION);
					glVertex3f((i+1)*MAX_X / DIVISION, 0, j * MAX_Z / DIVISION);
					glVertex3f((i+1)*MAX_X / DIVISION, 0, (j+1) * MAX_Z / DIVISION);
					glVertex3f(i*MAX_X / DIVISION, 0, (j+1) * MAX_Z / DIVISION);
				glEnd();
			}
	}

	if (UnVect * CVector3(1, 0, 0) > 0)
	{
		// Plan x = 0
		for (i = 0; i < DIVISION; i++)
			for (j = 0; j < DIVISION; j++)
			{
				glBegin(GL_QUADS);
					glNormal3f(-1.0, 0.0, 0.0);
					glVertex3f(0, i*MAX_Y/ DIVISION, j * MAX_Z / DIVISION);
					glVertex3f(0, (i+1)*MAX_Y / DIVISION, j * MAX_Z / DIVISION);
					glVertex3f(0, (i+1)*MAX_Y / DIVISION, (j+1) * MAX_Z / DIVISION);
					glVertex3f(0, i*MAX_Y / DIVISION, (j+1) * MAX_Z / DIVISION);
				glEnd();
			}
	}


	UnVect = gCamera.Position - CVector3(MAX_X, MAX_Y, 0);

	if (UnVect * CVector3(0, -1, 0) > 0)
	{
		// Plan y = MAX_Y
		for (i = 0; i < DIVISION; i++)
			for (j = 0; j < DIVISION; j++)
			{
				glBegin(GL_QUADS);
					glNormal3f(0.0, 1.0, 0.0);
					glVertex3f(i*MAX_X / DIVISION, MAX_Y, j * MAX_Z / DIVISION);
					glVertex3f((i+1)*MAX_X / DIVISION, MAX_Y, j * MAX_Z / DIVISION);
					glVertex3f((i+1)*MAX_X / DIVISION, MAX_Y, (j+1) * MAX_Z / DIVISION);
					glVertex3f(i*MAX_X / DIVISION, MAX_Y, (j+1) * MAX_Z / DIVISION);
				glEnd();
			}
	}

	if (UnVect * CVector3(-1, 0, 0) > 0)
	{
		// Plan x = MAX_X
		for (i = 0; i < DIVISION; i++)
			for (j = 0; j < DIVISION; j++)
			{
				glBegin(GL_QUADS);
					glNormal3f(1.0, 0.0, 0.0);
					glVertex3f(MAX_X, i*MAX_Y/ DIVISION, j * MAX_Z / DIVISION);
					glVertex3f(MAX_X, (i+1)*MAX_Y / DIVISION, j * MAX_Z / DIVISION);
					glVertex3f(MAX_X, (i+1)*MAX_Y / DIVISION, (j+1) * MAX_Z / DIVISION);
					glVertex3f(MAX_X, i*MAX_Y / DIVISION, (j+1) * MAX_Z / DIVISION);
				glEnd();
			}
	}
}
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;
	}

	wout.SetPos(10, (CENTRE_Y << 1) - 20);
	wout << AncienCompteur;
	wout.flush();
}




void DrawEspace(void)
{
	wout.Begin();
		glViewport(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);

		FPS();

		glDepthMask(false);
		glColor3f(0.0f, 0.0f, 0.3f);
		glBegin(GL_QUADS);
			glVertex2f(SCREEN_WIDTH - LARGEURTEXTE, 0);
			glVertex2f(SCREEN_WIDTH - LARGEURTEXTE, SCREEN_HEIGHT);
			glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
			glVertex2f(SCREEN_WIDTH, 0);
		glEnd();

		glColor3f(0.0f, 0.0f, 0.0f);
		glBegin(GL_QUADS);
			glVertex2f(SCREEN_WIDTH - LARGEURTEXTE + BORDURE, SCREEN_HEIGHT * 2/3 + BORDURE);
			glVertex2f(SCREEN_WIDTH - LARGEURTEXTE + BORDURE, SCREEN_HEIGHT - BORDURE);
			glVertex2f(SCREEN_WIDTH - BORDURE, SCREEN_HEIGHT - BORDURE);
			glVertex2f(SCREEN_WIDTH - BORDURE, SCREEN_HEIGHT * 2 / 3 + BORDURE);
		glEnd();
		glDepthMask(true);

		wout.SetCouleur(1,1,1,1);

		unsigned char Niveau[] = "Niveau:";
		wout.SetPos(SCREEN_WIDTH - (LARGEURTEXTE >> 1) - (wout.Length(Niveau) >> 1), CENTRE_Y);
		wout << Niveau << std::endl << std::endl;
		wout.flush();
		wout.SetPos(SCREEN_WIDTH - (LARGEURTEXTE >> 1), wout.y);
		wout << gJeu.Niveau;
		wout.flush();

		unsigned char Plans[] = "Nombre de plans:";
		wout.SetPos(SCREEN_WIDTH - (LARGEURTEXTE >> 1) - (wout.Length(Plans) >> 1), CENTRE_Y >> 1);
		wout << Plans << std::endl << std::endl;
		wout.flush();
		wout.SetPos(SCREEN_WIDTH - (LARGEURTEXTE >> 1), wout.y);
		wout << gJeu.NombreDePlans;
		wout.flush();

		// Dessin du bloc de preview
		glViewport(SCREEN_WIDTH - LARGEURTEXTE + BORDURE, SCREEN_HEIGHT * 2/3 + BORDURE,
				   LARGEURTEXTE - (BORDURE << 1), SCREEN_HEIGHT / 3 - (BORDURE << 1));
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
			glLoadIdentity();
			gluPerspective(50.0, (float) (LARGEURTEXTE - (BORDURE << 1)) / 
						   (float) (SCREEN_HEIGHT / 3 - (BORDURE << 1)), 0.1, 100);
		
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
			glLoadIdentity();
			float theta = (GetTemps() - gJeu.BlocPreview.Temps0Preview) * SPEEDROTPREVIEW;
			gluLookAt(DISTROT*cos(theta), DISTROT*sin(theta), 2.0f, 0, 0, 0, 0, 0, 1);

		for (int i = 0; i < gJeu.BlocPreview.LesCubes.size(); i++)
			gJeu.BlocPreview.LesCubes[i].Draw();
		
		glPopMatrix();	
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
	

		glViewport(0,0, SCREEN_WIDTH - LARGEURTEXTE, SCREEN_HEIGHT);
	wout.End();

	Plan();
	Boite();
}