/*********************************************************************
 *
 *                  Emulateur Visualisateur Eprom
 *                      27C256 pour calculateurs
 *                       DIFIGANT VW POLO G40
 *
 *
 *********************************************************************
 * Nom Fichier:     main.cpp
 *
 * Compilateur:     GCC
 *
 * Auteur:          F.KERMARREC (FloConcept)
 *
 * Date:            24/03/09
 *
 * Description:     Fichier principal du logiciel d'emulation et
 *                  visualisation d'eprom 27c256.
 *
  ********************************************************************/

//Librairies principales
#include "utils.h"

//Librairies d'inteface graphique
#include "Widget.h"
#include "Eprom.h"
#include "Com.h"


//Constantes
#define n 0.2

//Constantes/Variables relatives aux
//ouverture des fichiers
#define rep_eproms "fichiers/eproms/"
#define eprom_filename_size 80
#define eprom_nb_max 50
char  selected_eprom[eprom_filename_size];
char  liste_eproms[eprom_nb_max][eprom_filename_size];
int   nb_eproms;
Eprom eprom_sel;
int   selection  = 0;

//Variables d'etat
int affichage = 0;
int pause = 0;
int quitter = 0;
int changement = 0;
int rpm = 0;
int pressure = 0;
int value = 0;

//Variables d'orientation
//de la figure Open GL
double alpha = 0;
double theta = 0;
double phi = 0;

double alpha_saved = 0;
double theta_saved = 0;
double phi_saved = 0;

//Variables fenêtre SDL
SDL_Color color;
SDL_Rect position;
SDL_Event event;
TTF_Font* font;
TTF_Font* font14;

void generationListeEproms()
{
	struct dirent *lecture;
	DIR *rep;
	rep = opendir(rep_eproms);
	while ((lecture = readdir(rep)))
	{
		if (*(lecture->d_name)!='.')
		sprintf(liste_eproms[nb_eproms++],"%s",lecture->d_name);
	}
	closedir(rep);
}

void affichageListeEproms()
{
	//Affectation des couleurs
	color.r = 231;
	color.g = 191;
	color.b = 62;

	//Affectation de la position
	position.x = 10;
	position.y = 10;
	//Affichage
	SDL_GL_RenderText(rep_eproms,font, color, &position);

	int i;
	i=4;
	position.y += 8;
	for(i=0;i<nb_eproms;i++)
	{
		if (i==selection)
		{
			color.r = 231;
			color.g = 191;
			color.b = 62;
		}
		else
		{
			color.r = 120;
			color.g = 120;
			color.b = 120;
		}
	SDL_GL_RenderText(liste_eproms[i],font,color,&position);
	position.y += 8;
	}
}

void affichageRupteur(int rupteur)
{
	position.x = 10;
	position.y = 20+nb_eproms*10;
	color.r = 231;
	color.g = 191;
	color.b = 62;
	TTF_Font* _font;
	_font = TTF_OpenFont(fontpath, 14);
	SDL_GL_RenderText("Rupteur",_font, color, &position);
	char buffer[30];
	sprintf(buffer,"%d tr/min",rupteur);
	position.x = 10;
	position.y = 30+nb_eproms*10;
	color.r = 120;
	color.g = 120;
	color.b = 120;
	SDL_GL_RenderText(buffer,_font, color, &position);
}

void affichageTempsInjection(int TempsInjection)
{
	position.x = 10;
	position.y = 50+nb_eproms*10;
	color.r = 231;
	color.g = 191;
	color.b = 62;
	TTF_Font* _font;
	_font = TTF_OpenFont(fontpath, 14);
	SDL_GL_RenderText("Temps Injection",_font, color, &position);
	char buffer[30];
	sprintf(buffer,"%d",TempsInjection);
	position.x = 10;
	position.y = 60+nb_eproms*10;
	color.r = 120;
	color.g = 120;
	color.b = 120;
	SDL_GL_RenderText(buffer, _font, color, &position);
}

void affichageAvanceAllumage(int AvanceAllumage)
{
	position.x = 10;
	position.y = 80+nb_eproms*10;
	color.r = 231;
	color.g = 191;
	color.b = 62;
	TTF_Font* _font;
	_font = TTF_OpenFont(fontpath, 14);
	SDL_GL_RenderText("Avance Allumage", _font, color, &position);
	char buffer[30];
	sprintf(buffer,"%d", AvanceAllumage);
	position.x = 10;
	position.y = 90+nb_eproms*10;
	color.r = 120;
	color.g = 120;
	color.b = 120;
	SDL_GL_RenderText(buffer, _font, color, &position);
}
void affichageCommentaires(int w, int h)
{
	position.x = w-200;
	position.y = 100;
	color.r = 231;
	color.g = 191;
	color.b = 62;
	SDL_GL_RenderText("Touches:",font, color, &position);
	color.r = 120;
	color.g = 120;
	color.b = 120;

	position.y = 90;
	SDL_GL_RenderText("U/J : modifier rupteur",font, color, &position);
	position.y = 80;
	SDL_GL_RenderText("Haut/Bas : parcourir eproms",font, color, &position);
	position.y = 70;
	SDL_GL_RenderText("Droite/Gauche : Carte Injection/Avance",font, color, &position);
	position.y = 60;
	SDL_GL_RenderText("Espace : pause",font, color, &position);
	position.y = 50;
	SDL_GL_RenderText("Z/Q/S/D : se deplacer sur la carto",font, color, &position);
	position.y = 40;
	SDL_GL_RenderText("P/M : modifier la carto",font, color, &position);
	position.y = 30;
	SDL_GL_RenderText("O/L : translater la carto (pourcentage)",font, color, &position);
	position.y = 20;
	SDL_GL_RenderText("I/K : translater la carto (increment)",font, color, &position);	
	position.y = 10;
	SDL_GL_RenderText("W : sauvegarder la carto",font, color, &position);
}

void affichageTitre()
{
	color.r = 231;
	color.g = 191;
	color.b = 62;

	position.x = 500;
	position.y = 750;

	if(affichage < 2)
	{
		SDL_GL_RenderText("Injection",font14, color, &position);
	} else {
		SDL_GL_RenderText("Allumage",font14, color, &position);
	}
}

void affichagePressionRegime(int w, int h)
{
	//Pression
	position.x = w-200;
	position.y = 120;
	color.r = 231;
	color.g = 191;
	color.b = 62;
	SDL_GL_RenderText("Pression",font14, color, &position);
	char buffer[30];
	sprintf(buffer,"%f Bar",2.0*(pressure+1)/16-1);
	position.x = w-200;
	position.y = 130;
	color.r = 120;
	color.g = 120;
	color.b = 120;
	SDL_GL_RenderText(buffer,font14, color, &position);

	//Régime
	position.x = w-200;
	position.y = 150;
	color.r = 231;
	color.g = 191;
	color.b = 62;
	SDL_GL_RenderText("Regime",font14, color, &position);
	sprintf(buffer,"%d Tr/Min",(6800*(rpm+1))/16);
	position.x = w-200;
	position.y = 160;
	color.r = 120;
	color.g = 120;
	color.b = 120;
	SDL_GL_RenderText(buffer,font14, color, &position);
}

//Fonction principale
int main(int argc, char *argv[])
{


	int enable_mouse;
	enable_mouse = 0;

	//Com
	Com serial;
	serial.open(3, 115200);

	//Recherche des eproms présentes
	generationListeEproms();

	//Chargement de la premiere eprom de la liste
	Eprom eprom_sel;
	sprintf(selected_eprom,"%s%s",rep_eproms,liste_eproms[selection]);
	eprom_sel.lectureFichier(selected_eprom);

	//Initialisation SDL
	init_sdl();
    SDL_EnableUNICODE(1);
	//Initialisation OpenGL
	init_gl();


	//Tant que l'arret du programme n'est pas demandé
	//on effectue cette boucle
	while(!quitter) {
		font = TTF_OpenFont(fontpath, 8);
		font14 = TTF_OpenFont(fontpath, 14);
		
		//Reglage Camera
		eprom_sel.reglageCamera(alpha ,theta, phi);
		
		//Reinitialisation Open GL
		glClear(GL_COLOR_BUFFER_BIT);
		glMatrixMode(GL_MODELVIEW );
		glLoadIdentity();
		gluLookAt(30*8,30*8,30*8,0,0,0,0,0,1);

		//Affichage 3D
		if (affichage == 0) eprom_sel.affichageInjection(0,0,-100, rpm, pressure);
		else if (affichage == 1) eprom_sel.affichageInjection2D(0,0,-100, rpm, pressure);
		else if (affichage == 2) eprom_sel.affichageAvance(0,0,-100, rpm, pressure);
		else if (affichage == 3) eprom_sel.affichageAvance2D(0,0,-100, rpm, pressure);

		//Affichage 2D
		glEnable2D();

		//Affichage du titre
		affichageTitre();

		//Affichage du repertoire contenant
		//les eproms
		affichageListeEproms();

		//Affichage du rupteur
		affichageRupteur(eprom_sel.getRupteur());

		//Affichage des commentaires
		affichageCommentaires(1024, 768);

		//Affichage du temps injection
		affichageTempsInjection(eprom_sel.readInjection(rpm, pressure));

		//Affichage du avance allumage
		affichageAvanceAllumage(eprom_sel.readAvance(rpm, pressure));

		//Affichage Pression / Régime
		affichagePressionRegime(1024, 768);
		

		//Affichage connection
		serial.draw();

		SDL_PumpEvents();
		TTF_CloseFont(font);
		glDisable2D();
		glFlush();
		int space_detected = 0;


		if (!pause) theta ++;

		SDL_GL_SwapBuffers();

		if (SDL_PollEvent(&event))
		{
			switch(event.type)
			{
				case SDL_QUIT:
					quitter = true;
					break;

				case SDL_MOUSEBUTTONDOWN:
					if (event.button.button == SDL_BUTTON_LEFT) {
						enable_mouse = 1;
					}
					break;
				case SDL_MOUSEBUTTONUP:
					enable_mouse = 0;
					break;
				case SDL_MOUSEMOTION:
					if (enable_mouse){
				   		theta += event.motion.xrel;
				   		alpha += event.motion.yrel;
	      		   	}
	      		   break;
				case SDL_KEYDOWN:
					switch (event.key.keysym.unicode)
					{
						case SDLK_ESCAPE:
							quitter = true;
							break;
						case SDLK_p:
							if (affichage < 2)
							{
								eprom_sel.writeInjection(rpm,pressure,eprom_sel.readInjection(rpm,pressure)+1);
							}
							else
							{
								eprom_sel.writeAvance(rpm,pressure,eprom_sel.readAvance(rpm,pressure)+1);
							}
							break;
						case SDLK_m:
							if (affichage < 2)
							{
								eprom_sel.writeInjection(rpm,pressure,eprom_sel.readInjection(rpm,pressure)-1);
							}
							else
							{
								eprom_sel.writeAvance(rpm,pressure,eprom_sel.readAvance(rpm,pressure)-1);
							}
							break;
						case SDLK_d:
							if (rpm != 15)
								rpm = rpm + 1;
							break;
						case SDLK_q:
							if (rpm != 0)
								rpm = rpm - 1;
							break;
						case SDLK_z:
							if (pressure != 15)
								pressure = pressure + 1;
							break;
						case SDLK_s:
							if (pressure != 0)
								pressure = pressure - 1;
							break;
						case SDLK_w:
							eprom_sel.ecritureFichier(selected_eprom);
							break;
						case SDLK_x:
							eprom_sel.ecritureFichier(selected_eprom);
							serial.eeprom_write_table(AVANCE_TABLE_OFFSET, 256, eprom_sel.rom);
							serial.eeprom_write_table(INJECTION_TABLE_OFFSET, 256, eprom_sel.rom);
							serial.eeprom_write_table(RUPTEUR_OFFSET, 16, eprom_sel.rom);
							break;
						case SDLK_o:
							if (affichage < 2) eprom_sel.multInjection(1.01);
							else eprom_sel.multAvance(1.01);
							break;
						case SDLK_l:
							if (affichage < 2) eprom_sel.multInjection(0.99);
							else eprom_sel.multAvance(0.99);
							break;
						case SDLK_i:
							if (affichage < 2) eprom_sel.addsubInjection(1.00);
							else eprom_sel.addsubAvance(1.00);
							break;
						case SDLK_k:
							if (affichage < 2) eprom_sel.addsubInjection(-1.00);
							else eprom_sel.addsubAvance(-1.00);
							break;
						case SDLK_u:
							eprom_sel.setRupteur(eprom_sel.getRupteur()+2);
							break;
						case SDLK_j:
							eprom_sel.setRupteur(eprom_sel.getRupteur()-2);
							break;						
						default:
							break;
					}
       				switch (event.key.keysym.sym)
       				{
       				  case SDLK_UP:
       				    selection++;
       				    if (selection == nb_eproms) selection = 0;
       				    sprintf(selected_eprom,"%s%s","fichiers/eproms/",liste_eproms[selection]);
       				    eprom_sel.lectureFichier(selected_eprom);
       				    break;
       				  case SDLK_DOWN:
       				    selection --;
       				    if (selection == -1) selection = nb_eproms - 1;
       				    sprintf(selected_eprom,"%s%s","fichiers/eproms/",liste_eproms[selection]);
       				    eprom_sel.lectureFichier(selected_eprom);
       				    break;
       				  case SDLK_SPACE:
       				    if (pause) pause = 0;
       				    else pause = 1;
       				    space_detected = 1;
       				    break;
       				  case SDLK_RIGHT:
       				  	if (affichage == 1 || affichage == 3) {
							float alpha_tmp = alpha;
							float theta_tmp = theta;
							float phi_tmp = phi;

							alpha = alpha_saved;
							theta = theta_saved;
							phi = phi_saved;

							alpha_saved = alpha_tmp;
							theta_saved = theta_tmp;
							phi_saved = phi_tmp;      				  		
       				  	}
       				    if (affichage == 3) affichage = 0;
       				    else affichage = affichage + 1;
       				    break;
       				  case SDLK_LEFT:
       				  	if (affichage == 0 || affichage == 2) {
							float alpha_tmp = alpha;
							float theta_tmp = theta;
							float phi_tmp = phi;

							alpha = alpha_saved;
							theta = theta_saved;
							phi = phi_saved;

							alpha_saved = alpha_tmp;
							theta_saved = theta_tmp;
							phi_saved = phi_tmp;        				  		
       				  	}

       				    if (affichage == 0) affichage = 3;
       				    else affichage = affichage - 1;
       				    break;
       				  default:
       				    break;
       				}

			break;
			}
		}
	SDL_Delay(dt);
	}

	return 0;
}