 
#include <iostream>

#ifdef WIN32
#include <windows.h>
#endif
/*#include "GL\gl.h"
#include "GL\glu.h"*/
#include "GL\glut.h"
#include "GL\glext.h"
#include "glut_base_callback.h"

#include "ConsoleCommand.h"
#include "SimpleCamera.h"
#include "RTSCamera.h"
#include "Texture2D.h"
#include "glFont2D.h"
#include "ModelStatic.h"
#include "ModelInstance.h"

#include "GroundMap.h"
#include "ZoneManager.h"
#include "MatrixPathFinder.h"
#include "Renderer.h"
#include "DecorManager.h"

#include "VisibilityChecker.h"
#include "VisibilityArea.h"
#include "RenderableEntity.h"

#include "ArmyStupid.h"
#include "ArmyStupid2.h"
#include "BasicAI.h"
#include "DebugAI.h"

#include "UnitActionManager.h"
#include "CollisionManager.h"
#include "GroupPathFinder.h"
#include "GroupPathFinderManager.h"
#include "GroundArmyInfo.h"

#include "Config.h"

#include "Unit.h"
#include "Archer.h"
#include "Infantry.h"
#include "Lancer.h"
#include "Mount.h"

#include "MemoryManager/debugNew.h"

//Juste pour test
#include "Fresh.h"
#include "OutDatedZone.h"
#include "FreshZone.h"
#include "Force.h"
#include "ForceHigh.h"

bool drawPath = false;

using namespace ground;
using namespace RenderSystem;

bool usingRTSCamera	= false;
SimpleCamera* cam;
RTSCamera* rtsCam;

glFont2D* glfont;
Texture2D* glfont_tex;

Console *console;


float curMX,curMY;					//courante position de la souris
float lastMX,lastMY;				//dernière position de la souris
bool mouseMiddlePressed = false;	//boutton milieu de la souris enfoncé?


extern int screenWidth;
extern int screenHeight;


//pour le temp
int elapsedTimes = 0;
int lastTime = 0;
int tempTime = 0;
int gameTime = 0;
int IAupdateTime = 0;

// pour smoother les mouvement de la camera en mode rts
float maxVariationPerSeconde = 15.0f;

//variable de debuggage
bool debugElevation = false;

Army* army1;
Army* army2;
bool pause = true;
int saveIAupdateTime = 0;
int saveGameTime = 0;

void quitProg()
{
	delete cam;
	delete rtsCam;
	delete glfont;
	delete glfont_tex;

	delete army1;
	delete army2;

	// bien appeler le destructeur de decor avant de detruire le renderer car sinon les models
	// sont detruit et ne peuvent plus relacher les instance.
	FreeMountManager::destroy();
	Config::destroy();
	CollisionManager::destroy();
	UnitActionManager::destroy();
	DecorManager::destroy();
	Renderer::destroy();
	ZoneManager::destroy();
	GroundMap::destroy();
	TextureManager::destroy();
	GroupPathFinderManager::destroy();
	delete console;
	glutLeaveGameMode();
	exit(0);
}

void glut_base_dessin(void)
{
	//on efface le buffer couleur et depth et on poisitionne la matrice modelview(par defaut ici) à l'identité.
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	//on positionne la caméra qu'on utilise
	if(usingRTSCamera)
		rtsCam->gluLookAt();
	else
		cam->gluLookAt();

	//affichage du repere
	glLineWidth(5);
	glBegin(GL_LINES);
	glColor3f(1,0,0);
	glVertex3f(0,0,0);
	glVertex3f(10,0,0);
	glColor3f(0,1,0);
	glVertex3f(0,0,0);
	glVertex3f(0,10,0);
	glColor3f(0,0,1);
	glVertex3f(0,0,0);
	glVertex3f(0,0,10);
	glEnd();
	glLineWidth(1);

	float pos[3];
	Frustum f;
	if(usingRTSCamera) {
		pos[0] = rtsCam->p.getPosition()->x;
		pos[2] = rtsCam->p.getPosition()->z;
		float cameraHeight = rtsCam->p.getPosition()->y;
		float destinationCameraHeight = 35 + Renderer::getInstance().getElevationWorldCoord(pos[0],pos[2]);
		if (cameraHeight < destinationCameraHeight){
			cameraHeight+= maxVariationPerSeconde*elapsedTimes*0.001;
			if (cameraHeight > destinationCameraHeight){
				cameraHeight = destinationCameraHeight;
			}
		}else if(cameraHeight > destinationCameraHeight){
			cameraHeight-= maxVariationPerSeconde*elapsedTimes*0.001;
			if (cameraHeight < destinationCameraHeight){
				cameraHeight = destinationCameraHeight;
			}
		}
		rtsCam->p.setPosition(pos[0],cameraHeight,pos[2]);
		pos[1] = cameraHeight;
	}
	else {
		pos[0] = cam->p.getPosition()->x;
		pos[1] = cam->p.getPosition()->y;
		pos[2] = cam->p.getPosition()->z;
	}
	//on créer un objet frustum positionner sur la matrice courante de modelView
	f.update();

	//rendu du niveau
	Renderer::getInstance().beginFrame(elapsedTimes);
	Renderer::getInstance().render(pos,&f);
	Renderer::getInstance().endFrame();


	if(debugElevation)
	{
		float x,y,z;
		if(usingRTSCamera) {
			x = rtsCam->p.getPosition()->x;
			z = rtsCam->p.getPosition()->z;
		}
		else
		{
			x = cam->p.getPosition()->x;
			z = cam->p.getPosition()->z;
		}
		//y = Renderer::getInstance().getElevation(x/CASE_SIDE_SIZE,z/CASE_SIDE_SIZE);
		y = Renderer::getInstance().getElevationWorldCoord(x,z);

		glColor3f(1.0f,0.0f,0.0f);
		glPointSize(10.0f);
		glBegin(GL_POINTS);
		glVertex3f(x,y,z);
		glEnd();
		glPointSize(1.0f);
		glfont->setProjection2DForGLFont2D(0,133,0,100);
		glColor3f(1.0f,1.0f,1.0f);
		glfont->renderText2D(0,0,"%f, %f, %f",x,y,z);
		glfont->unsetProjection2DForGLFont2D();
	}

	//rendu de la console si elle est ouverte
	if(console->isOpen())
		console->render();

	//on flush les commande OpenGL...
	glFlush();
	//...puis on swap les 2 buffer de rendu
	glutSwapBuffers();
}

void glut_base_programme(void)
{
	const float IAupdateTimeLimite = 1000.0f;
	//temps écoulé depuis la dernière frame
	tempTime = glutGet(GLUT_ELAPSED_TIME);
	elapsedTimes = tempTime - lastTime;
	lastTime = tempTime;
	if (!pause){
		gameTime += elapsedTimes;
		IAupdateTime += elapsedTimes;

		while(IAupdateTime>3*IAupdateTimeLimite) {
			IAupdateTime -= 3*IAupdateTimeLimite;
			army1->updateAI();
			army2->updateAI();
		}
		while(gameTime >= (1000/25.0f)){
			gameTime -= (1000/25.0f);
			army1->updateUnit();
			army2->updateUnit();
			// on gere les collisions
			CollisionManager::getInstance().processCollisions();
			// on detruit toute les actions qui ont été liberée
			UnitActionManager::getInstance().freeActions();
			// on verifie si les groupes d'unité sont arrivé ou pas.
			GroupPathFinderManager& manager = GroupPathFinderManager::getInstance();
			GroupPathFinderManager::getInstance().update();
		}
	}


	//update de la console
	console->update(elapsedTimes);

	//update de la caméra utilisé
	if(usingRTSCamera) {
		rtsCam->computeMovement(elapsedTimes);
		rtsCam->setLastMouseMove(0.0f,0.0f);
		if (curMX > screenWidth){
			curMX = screenWidth;
		}
		if (curMX < 0){
			curMX = 0;
		}
		if (curMY > screenHeight){
			curMY = screenHeight;
		}
		if (curMY < 0){
			curMY = 0;
		}
		glutWarpPointer(curMX,curMY);
	}
	else {
		cam->setLastMouseMove(curMX-(screenWidth/2),(screenHeight/2)-curMY);
		cam->computeMovement(elapsedTimes);
		glutWarpPointer(screenWidth/2,screenHeight/2);
	}
	lastMX = curMX;
	lastMY = curMY;


	//on demande l'affichage suivant
	glutPostRedisplay();
}

void glut_base_sourisClic(int boutton,int etat,int x,int y)
{
	curMX=x;
	curMY=y;

	if(usingRTSCamera) {
		//lastMX=x-lastMX;
		//lastMY=y-lastMY;
	}
	else {
		lastMX=x;
		lastMY=y;
	}

	if(usingRTSCamera) {
		rtsCam->setCurMousePos(curMX,curMY);
		if(boutton==GLUT_MIDDLE_BUTTON && etat==GLUT_DOWN)
			mouseMiddlePressed = true;
		if(boutton==GLUT_MIDDLE_BUTTON && etat==GLUT_UP)
			mouseMiddlePressed = false;
	}
}

void glut_base_sourisClicMove(int x,int y)
{
	curMX=x;
	curMY=y;

	if(usingRTSCamera) {
		//la souris a changer de poisition avec un bouton enfoncé
		rtsCam->setCurMousePos(curMX,curMY);
		if(mouseMiddlePressed)
			//on apuye sur le bouton pour régler la tete : on indique le mouvement de la souris
			rtsCam->setLastMouseMove(curMX-lastMX,curMY-lastMY);
	}
}

void glut_base_sourisMove(int x,int y)
{
	curMX=x;
	curMY=y;

	//la souris a changer de poisition
	rtsCam->setCurMousePos(curMX,curMY);
}

void glut_base_clavier(unsigned char key,int x,int y)
{
	Unit* u = NULL;

	if(console->isOpen())
	{
		console->keyTyped(key);
	}
	else
	{
		switch(key)
		{
		case CONSOLE_CLOSE:
			console->Open();
			break;
			
		case 'b':
			printf("breakPoint\n");
			break;
		case 'q':
			if(!usingRTSCamera)
				cam->setGauche(true);
			break;
		case 'd':
			if(!usingRTSCamera)
				cam->setDroite(true);
			break;
		case 'z':
			if(!usingRTSCamera)
				cam->setAvance(true);
			break;
		case 's':
			if(!usingRTSCamera)
				cam->setRecule(true);
			break;
		case ' ':
			if(!usingRTSCamera)
				cam->setHaut(true);
			break;
		case 'c':
			if(!usingRTSCamera)
				cam->setBas(true);
			break;
		case 'p':
			pause = !pause;
			if(pause){
				Renderer::getInstance().timeFactor = 0.0f;
			}else{
				Renderer::getInstance().timeFactor = 1.0f;
			}
			break;

		/*case 'u':
			u = new Archer();
			if(usingRTSCamera) u->setPosition(Point2D(rtsCam->p.getPosition()->x/CASE_SIDE_SIZE,rtsCam->p.getPosition()->z/CASE_SIDE_SIZE));
			else  u->setPosition(Point2D(rtsCam->p.getPosition()->x/CASE_SIDE_SIZE,rtsCam->p.getPosition()->z/CASE_SIDE_SIZE));
			armyInfo->addUnit(u);
			unites->push_back(u);

			u->setProperties("Archer","Bleu");
			Renderer::getInstance().addRenderableEntity(*u);
			break;*/

		case '0':
			console->DispMsg(1.0f,1.0f,1.0f,1.0f,"on suit l'armee 1");
			Renderer::getInstance().followArmy(0);
			break;
		case '1':
			console->DispMsg(1.0f,1.0f,1.0f,1.0f,"on suit l'armee 2");
			Renderer::getInstance().followArmy(1);
			break;
		case '2':
			console->DispMsg(1.0f,1.0f,1.0f,1.0f,"on suit les deux armee");
			Renderer::getInstance().followArmy(2);
			break;

		case 27:
			quitProg();
			break;
		}
	}
}


void quit(char* cmd, Console* csl)
{
	quitProg();
}


void glut_base_clavierup(unsigned char key,int x,int y)
{
	switch(key)
	{
	case 'q':
		if(!usingRTSCamera)
			cam->setGauche(false);
		break;
	case 'd':
		if(!usingRTSCamera)
			cam->setDroite(false);
		break;
	case 'z':
		if(!usingRTSCamera)
			cam->setAvance(false);
		break;
	case 's':
		if(!usingRTSCamera)
			cam->setRecule(false);
		break;
	case ' ':
		if(!usingRTSCamera)
			cam->setHaut(false);
		break;
	case 'c':
		if(!usingRTSCamera)
			cam->setBas(false);
		break;
	/*case 'p':
		{
			int x = fabs(cosf(rand()))*GroundMap::getInstance().getWidth();
			int y = fabs(cosf(rand()))*GroundMap::getInstance().getHeight();
			GroundMap::getInstance().setPathFinderMode(ground::pathFinding::FURTIF);
			GroundMap::getInstance().computeUnitPath(unit,Point2D(x,y));
			GroundMap::getInstance().setPathFinderMode(ground::pathFinding::NORMAL);
			(*path) = GroundMap::getInstance().getLastPath();
			unit->eraseAllAction();
			unit->goTo(*path);
		}
		break;*/
/*	case '1':
		unit->setAnimation(RenderableEntity::NO_ANIMATION);
		break;
	case '2':
		unit->setAnimation(RenderableEntity::WAIT);
		break;
	case '3':
		unit->setAnimation(RenderableEntity::WALK);
		break;
	case '4':
		unit->setAnimation(RenderableEntity::FIGHT);
		break;
	case '5':
		//unit->setAnimation(RenderableEntity::DEATH);
		break;*/
	}
}

void glut_base_specialKey(int key, int x, int y)
{
	if(console->isOpen())
	{
		switch(key)
		{
		case GLUT_KEY_LEFT:
			console->keyTyped(CONSOLE_LEFT);
			break;
		case GLUT_KEY_UP:
			console->keyTyped(CONSOLE_UP);
			break;
		case GLUT_KEY_RIGHT:
			console->keyTyped(CONSOLE_RIGHT);
			break;
		case GLUT_KEY_DOWN:
			console->keyTyped(CONSOLE_DOWN);
			break;
		case GLUT_KEY_PAGE_UP:
			console->keyTyped(CONSOLE_PG_UP);
			break;
		case GLUT_KEY_PAGE_DOWN:
			console->keyTyped(CONSOLE_PG_DOWN);
			break;
		case GLUT_KEY_HOME:
			console->keyTyped(CONSOLE_HOME);
			break;
		case GLUT_KEY_END:
			console->keyTyped(CONSOLE_END);
			break;
		case GLUT_KEY_INSERT:
			console->keyTyped(CONSOLE_INSERT);
			break;
		default:
			break;
		}
	}
	else
	{
		/*switch(key)
		{
		default:
			break;
		}*/
	}
}

void glut_base_fdim(int largeur,int hauteur)
{
	glViewport(0,0,(GLsizei) largeur,(GLsizei) hauteur);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(90,(float)largeur/(float)hauteur,1,FOG_DISTANCE);
	glMatrixMode(GL_MODELVIEW);
}

void z_findPath(char* cmd, Console* csl)
{
	if(strcmp(cmd,"z_findPath")==0)
	{
		csl->DispMsg(0,1,0,1,"calcule un chemin sur la carte");
		drawPath = !drawPath;
		if (drawPath){
			csl->DispMsg(0,0,1,1,"affichage du chemin active");
		}else{
			csl->DispMsg(0,0,1,1,"affichage du chemin desactive");
		}
	}
	else
	{
		/*float startX=0;
		float startY=0;
		float endX=0;
		float endY=0;
		if (sscanf(cmd,"z_findPath %f %f %f %f",&startX,&startY,&endX,&endY) == 4){
			int start = glutGet(GLUT_ELAPSED_TIME);
			GroundMap::getInstance().computePath(Point2D(startX,startY),Point2D(endX,endY));
			(*path) = GroundMap::getInstance().getLastPath();
			unit->eraseAllAction();
			unit->goTo(*path);
			int end = glutGet(GLUT_ELAPSED_TIME);
			if (!GroundMap::getInstance().haveFoundPath()){
				csl->DispMsg(1,1,0,1,"impossible de trouver un chemin");
			}else{
				csl->DispMsg(0,1,0,1,"chemin trouvé");
			}
			char buffer[512];
			sprintf(buffer,"temps ecoulé : %d ms\n",end - start);
			csl->DispMsg(0,1,0,1,buffer);
		}else{
			csl->DispMsg(0,1,0,1,"calcule un chemin sur la carte");
			csl->DispMsg(0,1,0,1,"    Parametres : startX startY endX endY");
		}*/
	}
}

void z_loadMap(char* cmd, Console* csl)
{
	if(strcmp(cmd,"z_loadMap")==0)
	{
		csl->DispMsg(0,1,0,1,"charge une carte");
	}
	else
	{
		string commande = cmd;
		size_t place = commande.find_last_of(" ")+1;
		string mapPath = "./maps/" + commande.substr(place);
		FILE * fichier = fopen(mapPath.c_str(),"r");
		if (fichier != NULL){
			fclose(fichier);
			
			/*for(std::vector<Unit*>::iterator it = unites->begin(); it != unites->end(); ++it){
				Unit * u = *it;
				delete u;
			}
			unites->clear();*/
			//armyInfo->removeAllUnits();
			

			csl->DispMsg(1.0,0,0,1.0,"a refaire en génerant de nouvelle armee...");
			return;
			
			GroundMap::destroy();
			ZoneManager::destroy();
			Renderer::destroy();

			//if(GroundMap::getInstance().loadMap((char*)mapPath.c_str()))				{
			//	std::cout<<"MAP loaded."<<std::endl;
			//	ZoneManager::getInstance().loadZoneAxe(GroundMap::getInstance(),mapPath);
			//	Renderer::getInstance().loadGroundMap(GroundMap::getInstance(),"textures/tileset/forest/");
			//	
			//	// On remet l'unité de tester
			//	// TODO : a supprimer
			//	/*unit = new Archer();
			//	unit->setOrientation(rand()%360);
			//	unit->setPosition(Point2D(3,3));
			//	armyInfo->addUnit(unit);
			//	unites->push_back(unit);
			//	unit->setProperties("Archer","Rouge");
			//	unit->setArmy("Neutre");
			//	unit->setAnimation(RenderableEntity::FIGHT);
			//	Renderer::getInstance().addRenderableEntity(*unit);
			//	Renderer::getInstance().setVisibilityMatrix(armyInfo->getVisibilityMatrix());*/
			//}else{
			//	std::cout<<"MAP not loaded."<<std::endl;
			//	exit(0);
			//}
		}else{
			csl->DispMsg(0,1,0,1,"charge une carte");
			csl->DispMsg(0,1,0,1,"    Parametres : nom de la carte");
		}
	}
}

void glut_base_fenetre()
{
	srand(1024);
	// Ecriture de la console dans le fichier log.txt à la racine du projet
	//freopen("log.txt", "w", stdout);

	//redimensionnement
	glutReshapeFunc(glut_base_fdim);

	//affichage
	glutDisplayFunc(glut_base_dessin);

	//inactivité graphique
	glutIdleFunc(glut_base_programme);

	//souris
	glutMouseFunc(glut_base_sourisClic);
	glutMotionFunc(glut_base_sourisClicMove);
	glutPassiveMotionFunc(glut_base_sourisMove);

	//clavier
	glutKeyboardFunc(glut_base_clavier);
	glutKeyboardUpFunc(glut_base_clavierup);
	glutSpecialFunc(glut_base_specialKey);

	cam = new SimpleCamera();
	rtsCam = new RTSCamera();

	cam->p.setPosition(10,20,30);
	cam->setProperties(0.002f,0.0009f,0.065f);
	rtsCam->setProperties(0.0009f,0.065,screenWidth,screenHeight);
	if(!usingRTSCamera)
			glutSetCursor(GLUT_CURSOR_NONE);

	glfont = new glFont2D();
	glfont_tex = new Texture2D();
	glfont_tex->loadBMP("font.bmp",true,GL_LINEAR,GL_LINEAR_MIPMAP_LINEAR,GL_CLAMP,GL_CLAMP,0,true,0,0,0,0,255,1);
	glfont->setHeight(2);
	glfont->setWidth(3);
	glfont->setIdTexFont(glfont_tex->getId());
	console = new Console(4.0f/3.0f,0.35f,50,glfont->getIdTexFont());

	string mapPath = Config::getInstance().getValue("game","map");
	char * mapName = (char*)mapPath.c_str();
	if (mapPath == ""){
		mapName = "maps/carte1.bmp";
	}
	string tileSet = Config::getInstance().getValue("game","tileSet");
	if (tileSet == ""){
		tileSet = "maps/carte1.bmp";
	}
	//char * mapName = "maps/islande.bmp";
	//char * mapName = "maps/carte1.bmp";
	//char * mapName = "maps/carte2.bmp";//512
	//char * mapName = "maps/carte3.bmp";//256
	//char * mapName = "maps/carte4.bmp";
	//char * mapName = "maps/carte5.bmp";
	//char * mapName = "maps/carteTest.bmp";
	//char * mapName = "maps/test128.bmp";//128
	//char * mapName = "maps/plaine.bmp";
	//char * mapName = "maps/testRectangle.bmp";
	//char * heightMapName = "maps/map1/height.bmp"; char * mapName = "maps/map1/type.bmp";
	//char * heightMapName = "maps/map2/height.bmp"; char * mapName = "maps/map2/type.bmp";
	//char * heightMapName = "maps/map3/height.bmp"; char * mapName = "maps/map3/type.bmp";
	//char * heightMapName = "maps/map4/height.bmp"; char * mapName = "maps/map4/type.bmp";

	if(GroundMap::getInstance().loadMap(mapName))
	//if(GroundMap::getInstance().loadMap(heightMapName,mapName))
	{
		std::cout<<"MAP loaded."<<std::endl;


		//////////////////////////////////////////// on créer les armées
		army1 = new ArmyStupid(std::string("Rouge"));
		army2 = new BasicAI(std::string("Bleu"));
		DebugAI::trace('i', "test debug");
		//((BasicAI*)army1)->setEnnemyArmy(army2);
		((ArmyStupid*)army1)->setEnnemyArmy(army2);


		//ZoneManager::getInstance().computeZoneAxe(GroundMap::getInstance());
		ZoneManager::getInstance().loadZoneAxe(GroundMap::getInstance(),mapName);
		Renderer::getInstance().loadGroundMap(GroundMap::getInstance(),(char*)tileSet.c_str(),*army1,*army2);
		Renderer::getInstance().followArmy(1);
		Renderer::getInstance().setGLFont(*glfont);
		//Renderer::getInstance().loadGroundMap(GroundMap::getInstance(),"textures/tileset/psycho/");
		//Renderer::getInstance().loadGroundMap(GroundMap::getInstance(),"textures/tileset/snow/");

		// une fois le renderer initilisé, on peut charger les decors puis calculer le graph de zones
		GroundMap::getInstance().loadDecors();
		GroundMap::getInstance().computeGraph();



		//////////////////////////////////////////// on peuple les armées
		army1->mapChanged();
		army2->mapChanged();

		army1->createUnits(unitEnumeration::INFANTRY, 8, Point2D(55,53), 3);
		army1->createUnits(unitEnumeration::LANCER, 4, Point2D(55,57), 3);
		army1->createUnits(unitEnumeration::ARCHER, 4, Point2D(55,55), 3);
		army2->createUnits(unitEnumeration::INFANTRY, 8, Point2D(10,10), 3);
		army2->createUnits(unitEnumeration::LANCER, 4, Point2D(10,10), 3);
		army2->createUnits(unitEnumeration::ARCHER, 4, Point2D(10,8), 3);

		//FreeMountManager::getInstance().createFreeMounts(3, Point2D(50,50), 5);
		//FreeMountManager::getInstance().createFreeMounts(8, Point2D(32,32), 32);
		//army1->createUnits(unitEnumeration::INFANTRY, Point2D(55,53), 2.5, 2,0,0.5f);
		//army1->createUnits(unitEnumeration::INFANTRY, Point2D(20,10), 5, 3,30,0.5f);
		//army1->createUnits(unitEnumeration::INFANTRY, Point2D(30,10), 5, 3,60,0.5f);

		//army2->createUnits(unitEnumeration::INFANTRY, Point2D(20,50), 5, 3,30,0.5f);
		//army1->createUnits(unitEnumeration::INFANTRY, Point2D(20,50), 5, 3,60,0.5f);

		//army1->createUnits(unitEnumeration::ARCHER, 10, Point2D(12,12), 2);
		//army2->createUnits(unitEnumeration::INFANTRY, 10, Point2D(12,12), 5);
		
		//army1->createUnits(unitEnumeration::LANCER, 10, Point2D(55,55), 5);
		//army1->createUnits(unitEnumeration::INFANTRY, 20, Point2D(55,55), 5);
	//	army1->createUnits(unitEnumeration::ARCHER, 5, Point2D(7,7), 5);
		//army2->createUnits(unitEnumeration::LANCER, 10, Point2D(5,5), 5);
		//army2->createUnits(unitEnumeration::INFANTRY, 20, Point2D(5,5), 5);
	//	army2->createUnits(unitEnumeration::ARCHER, 5, Point2D(5,5), 5);

		//army1->createUnits(unitEnumeration::LANCER, 10, Point2D(32,25), 20);
		//army1->createUnits(unitEnumeration::INFANTRY, 10, Point2D(32,25), 20);
		//army1->createUnits(unitEnumeration::ARCHER, 10, Point2D(32,25), 20);
		//army2->createUnits(unitEnumeration::LANCER, 10, Point2D(32,39), 20);
		//army2->createUnits(unitEnumeration::INFANTRY, 10, Point2D(32,39), 20);
		//army2->createUnits(unitEnumeration::ARCHER, 10, Point2D(32,39), 20);

		//army1->createUnits(unitEnumeration::LANCER, 10, Point2D(32,32), 32);
		//army1->createUnits(unitEnumeration::INFANTRY, 20, Point2D(32,32), 32);
		//army1->createUnits(unitEnumeration::ARCHER, 10, Point2D(32,32), 32);
		//army2->createUnits(unitEnumeration::LANCER, 10, Point2D(32,32), 32);
		//army2->createUnits(unitEnumeration::INFANTRY, 20, Point2D(32,32), 32);
		//army2->createUnits(unitEnumeration::ARCHER, 5, Point2D(32,32), 32);

		for(std::vector<Unit*>::iterator it = army1->getUnits().begin(); it != army1->getUnits().end(); ++it){
			((BasicAI*)army2)->getEnnemyManager()->addEnnemy(new EnnemyUnit(*it,EnnemyUnit::HIDDEN));
		}
		//for(std::vector<Unit*>::iterator it = army2->getUnits().begin(); it != army2->getUnits().end(); ++it){
		//	((BasicAI*)army1)->getEnnemyManager()->addEnnemy(new EnnemyUnit(*it,EnnemyUnit::HIDDEN));
		//}

		//((BasicAI*)army1)->manageGroups();
		((BasicAI*)army2)->manageGroups();


		/*armyInfo = new GroundArmyInfo();
		armyInfo->setupMapInfo(GroundMap::getInstance().getWidth(),GroundMap::getInstance().getHeight());
		vMatrix = new bool*[GroundMap::getInstance().getWidth()];
		for(unsigned int i=0;i<GroundMap::getInstance().getWidth();i++){
			vMatrix[i] = new bool[GroundMap::getInstance().getHeight()];
		}
		vChecker.setMatrixParameters(GroundMap::getInstance().getWidth(),GroundMap::getInstance().getHeight());
		vArea = new std::vector<ground::VisibilityArea*>();
		vArea->clear();
		vChecker.checkVisibility(vMatrix,*vArea);
		unites = new std::vector<Unit*>();
		mounts = new std::vector<Mount*>();
		Renderer::getInstance().setVisibilityMatrix(armyInfo->getVisibilityMatrix());*/
	}
	else
	{
		std::cout<<"MAP not loaded."<<std::endl;
		exit(0);
	}

	// ajout des fonctionnalitée propre a glut_base_callback.cpp
	console->addCommand("quit",quit);
	console->addCommand("z_findPath",z_findPath);
	console->addCommand("z_loadMap",z_loadMap);
	addFonctionnalityToConsole();
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#################################################");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#                                               #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"# PROJET IA :                                   #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#             ELEMENTS SEMANTIQUES TACTIQUES    #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#                  DANS UN UNIVERS 3D           #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#                                               #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"# Groupe Remi Cozot             IFSIC 2005/2006 #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#                                               #");
	console->DispMsg(1.0f,1.0f,1.0f,1.0f,"#################################################");

	//Renderer::getInstance().renderHiddenUnits = false;
	//Renderer::getInstance().renderParticles = true;
	//Renderer::getInstance().renderTreeLeaf = false;
	//Renderer::getInstance().renderTreeTrunk = false;
	//Renderer::getInstance().renderWaterZone = false;
	//Renderer::getInstance().renderDecors = false;
	//Renderer::getInstance().useGLFog = false;
	//Renderer::getInstance().useGLlighting = true;
	//Renderer::getInstance().useGroundTexture = true;
	//Renderer::getInstance().setFogOfWarAttributes(0.3f,1.0f);

/*	path = new std::vector<Point2D>();

	testUnit = new map<Unit*,Point2D>();
	
	unit = new Archer();
	unit->setOrientation(rand()%360);
	unit->setPosition(Point2D(28,32));
*///	Mount * mUnit = new Mount();
//	mUnit->setPosition(Point2D(10,10));
//	//unit->mountOn(mUnit);
//	cerr << "debut"<<endl;
//	mUnit->setProperties("Horse","Rouge");
//	cerr << "1"<<endl;
//	mUnit->setArmy("Neutre");
//	cerr << "2"<<endl;
//	Renderer::getInstance().addRenderableEntity(*mUnit);
//	cerr << "fin"<<endl;
/*	armyInfo->addUnit(unit);
	unit->setProperties("Archer","Rouge");
	unit->setArmy("Neutre");
	unit->setAnimation(RenderableEntity::FIGHT,unit->isMounted());
	unites->push_back(unit);
	//(*testUnit)[unit] = unit->getPosition();
	Renderer::getInstance().addRenderableEntity(*unit);
*/
	/*
	for (int i = 0; i < 90; i++){
		Unit * u = new Archer();
		int x;
		int y;
		Point2D dest;
		if (rand()%2 == 0){
			x = rand()%32+16;
			y = rand()%5 + 58;
			dest.setCoord(rand()%64,rand()%32);
			u->setProperties("Archer","Rouge");
		}else{
			x = rand()%32+16;
			y = rand()%5;
			dest.setCoord(rand()%64,rand()%32+32);
			u->setProperties("Archer","Bleu");
		}
		u->setPosition(Point2D(x,y));
		GroundMap::getInstance().computePath(Point2D(x,y),dest);
		u->goTo(GroundMap::getInstance().getLastPath());
		(*testUnit)[u] = dest;
		vArea->push_back(u);
		Renderer::getInstance().addRenderableEntity(*u);
	}
	GroupPathFinder group;*/
	//for (int i = 0; i < 20; i++){
	//	Unit * u = new Lancer();
	//	int x;
	//	int y;
	//	Point2D dest;
	//	x = rand()%8+28;
	//	y = rand()%5 + 58;
	//	u->setProperties("Lancer","Rouge");
	//	u->setPosition(Point2D(x,y));
	//	if (rand()%100 < 60){
	//		Mount * mount = new Mount();
	//		u->mountOn(mount);
	//		mount->setProperties("Horse","Rouge");
	//		Renderer::getInstance().addRenderableEntity(*mount);
	//		mounts->push_back(mount);
	//	}
	//	armyInfo->addUnit(u);
	//	Renderer::getInstance().addRenderableEntity(*u);
	//	group.addUnit(u);
	//	unites->push_back(u);
	//	(*testUnit)[u] = dest;
	//}
	/*int debut = glutGet(GLUT_ELAPSED_TIME);
	GroundMap::getInstance().moveGroupTo(group,Point2D(32,15));
	int fin = glutGet(GLUT_ELAPSED_TIME);
	printf("temps de calcul du pathfinding par groupe : %d\n",fin - debut);*/


	/*
	Unit * u1 = new Archer();
	u1->setProperties("Archer","Rouge");
	u1->setPosition(Point2D(32,42));
	armyInfo->addUnit(u1);
	Renderer::getInstance().addRenderableEntity(*u1);
	u1->goTo(Point2D(63,63));
	//GroundMap::getInstance().computePath(Point2D(3,3),Point2D(63,63));
	//u1->goTo(GroundMap::getInstance().getLastPath());
	unites->push_back(u1);
	(*testUnit)[u1] = u1->getPosition();
	//u1->wait();
	
	Unit * u2 = new Infantry();
	u2->setProperties("Infantry","Bleu");
	u2->setPosition(Point2D(26,42));
	Mount * u2mount = new Mount();
	mounts->push_back(u2mount);
	u2->mountOn(u2mount);
	u2mount->setProperties("Horse","Bleu");
	Renderer::getInstance().addRenderableEntity(*u2mount);
	armyInfo->addUnit(u2);
	Renderer::getInstance().addRenderableEntity(*u2);
	//GroundMap::getInstance().computeUnitPath(u2,Point2D(3,3));
	unites->push_back(u2);
	(*testUnit)[u2] = u2->getPosition();
	//u2->wait();
	//u2->goTo(GroundMap::getInstance().getLastPath());
	u2->goTo(Point2D(3,3));

	//
	Mount * m = new Mount();
	m->setPosition(Point2D(1,3));
	m->setProperties("Horse","Bleu");
	Renderer::getInstance().addRenderableEntity(*m);
	mounts->push_back(m);

	Unit * u3 = new Infantry();
	u3->setProperties("Infantry","Bleu");
	u3->setPosition(Point2D(5,5));
	armyInfo->addUnit(u3);
	Renderer::getInstance().addRenderableEntity(*u3);
	//GroundMap::getInstance().computePath(Point2D(5,5),Point2D(63,0));
	//u3->goTo(GroundMap::getInstance().getLastPath());
	u3->goTo(Point2D(63,0));
	unites->push_back(u3);
	(*testUnit)[u3] = u3->getPosition();
	u3->goAndMount(m);
*/

	/*** TEST FOLLOW ***/
	//u2 suit u1
	/*GroundMap::getInstance().computePath(Point2D(5,10),Point2D(10,10));
	u1->goTo(GroundMap::getInstance().getLastPath());
	//u2->follow(u1,2);
	u2->follow(u1);*/
/*
	EnnemyUnit * ennemy = new EnnemyUnit(u1,EnnemyUnit::VISIBLE);
	u2->attack(*ennemy);

	Unit* f1 = new Infantry();
	f1->setProperties("Infantry","Bleu");
	f1->setPosition(Point2D(1,3));
	armyInfo->addUnit(f1);
	Renderer::getInstance().addRenderableEntity(*f1);
	(*testUnit)[f1] = f1->getPosition();
	unites->push_back(f1);
	EnnemyUnit * e1 = new EnnemyUnit(f1,EnnemyUnit::VISIBLE);

	Unit* f2 = new Infantry();
	f2->setProperties("Infantry","Rouge");
	f2->setPosition(Point2D(1,15));
	armyInfo->addUnit(f2);
	Renderer::getInstance().addRenderableEntity(*f2);
	(*testUnit)[f2] = f2->getPosition();
	unites->push_back(f2);
	EnnemyUnit * e2 = new EnnemyUnit(f2,EnnemyUnit::VISIBLE);

	f1->attack(*e2);
	f2->attack(*e1);*/

	Renderer::getInstance().timeFactor = 0.0f;

	tempTime = glutGet(GLUT_ELAPSED_TIME);
	elapsedTimes = 0.0f;
	lastTime = tempTime;
}





