// UTS 2000 - Fichier 'garage.cpp' Lecture des variables pour les garages dans le fichier de configuration, et gestion de ces garages
// V3.7d - Le 24/10/2017
// Nombre de garages gérés par UTS = 'NB_GARAGE'.
/*****************************************************************************/
/* Début GARAGE                                                              */
/*****************************************************************************/
#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include  "garage.h"

#define _CRT_SECURE_NO_WARNINGS  // Limite les messages de warning dans Visual C++

// Déclaration des fonctions externes 
extern int get_line(FILE*, char [][CHAR_CONFIG_NB], int*);
extern void EasyTextOut(int, int, char*);
extern void EasyLine(int, int, int, int);
extern void garage_lock_and_unlock(void);
extern void bmp_select_brush(int no_color);

// Déclaration des variables externes
extern HBRUSH    bmp_pinceau_blanc, bmp_pinceau_gris192;
extern HDC       hMemDC;
extern HFONT     bmp_fonte;
extern HPEN      bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc;
extern int moins_char_normal;   // 1: '-' est un caractè re normal (comme 0)  0: '-' est un séparateur (comme +)
extern int x_mouse,y_mouse,touche,touche_char,x_mouse_move,y_mouse_move, screen_mode_retour;
extern int vio_out[NB_CARTE][NB_OUT];
extern int vio_garage_lock_cmd[NB_GARAGE]; // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
extern int vio_garage_lock_status[NB_GARAGE]; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
extern int vio_garage_lock_res[NB_GARAGE]; // 0 ou 1, 1 => Garage réservé.
extern int screen_mode;
extern char copy_train_name[NB_TRAIN][10];
extern int copy_garage_num_train[NB_GARAGE];
extern int color_train[NB_TRAIN];

//
//
cGarage  garage;
int cGarage::get_iti_line(FILE* pf, char ch_tab[][CHAR_CONFIG_NB], int* ch_nb)
{
	int ret;
	moins_char_normal=0;  // '-' n'est pas un caractère normal (so it is parsed)
	ret=get_line(pf,ch_tab,ch_nb);
	moins_char_normal=1;
	return ret;
}

// Sous programme pour récupérer les informations des garages dans le fichier 'config.txt' 
//
//
void cGarage::init(char filename[])
{
	FILE* pf;
	char ch[CHAR_CONFIG_NB],ch_tab[BLOC_CONFIG_NB][CHAR_CONFIG_NB],ch_error[200]; 
	int  ch_nb,i,num_garage;

	for (i=0; i<NB_GARAGE; i++) {
		ass_canton[i]=-1;
		ass_out[i]=0;
		ass_out_pol[i]=1;
		numero_train[i]=-1;
		vio_garage_lock_status[i]=0; // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
		vio_garage_lock_cmd[i]=0; // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
		vio_garage_lock_res[i]=0; // 0 ou 1, 1 => Garage réservé.
		copy_garage_num_train[i]=-1; // V4.3
	}
//
// g0: c1 out3 pol1
//
	if((pf=fopen(filename,"rt"))==NULL) {
		MessageBox(NULL,"Impossible d'ouvrir le fichier de configuration des garages 'Config.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
	}
	moins_char_normal=1; // '-' est un charactère normal (donc dans les chaînes)
	while(fscanf(pf,"%s%*[^\n]\n",ch)!=EOF) {	// " %s" => "%s%*[^\n]\n" = Nouvelle formule au 02/03/2012, lit uniquement le permier mot de chaque ligne.
		if(STR_SAME strcmp(ch,"#garage")) {
			fscanf(pf," %s",ch);				// Ignore le caractère '['
			while(get_line(pf,ch_tab,&ch_nb)) {
				num_garage=-1;
				if(ch_nb>=BLOC_CONFIG_NB) {
					MessageBox(NULL,"Le fichier config.txt comporte une ligne trop complexe dans la section '#garage'","Erreur",MB_OK|MB_ICONERROR);
					MessageBox(NULL,"Section '#garage' (ligne>75 blocs) commençant par (taper sur entrée) : ","Erreur",MB_OK|MB_ICONERROR);
					strcpy(ch_error,"Section #garage Erreur ligne :");
					for(i=0;i<ch_nb;i++) { strcat(ch_error,"  "); strcat(ch_error,ch_tab[i]); }
					MessageBox(NULL,ch_error,"UTS - Erreur",MB_OK|MB_ICONERROR); exit(1);
				}
				if(ch_tab[0][0]==']') break;			// Fin de la section #garage
				for(i=0;i<ch_nb;i++) if(ch_tab[i][0]=='@') ch_nb=i;  // Supprime les commentaires
				i=0;
				while(i<ch_nb) {
					// g0:
					if((ch_nb-i)>=2) {
						if( ch_tab[i][0]=='g' && ch_tab[i+1][0]==':') {
							num_garage=atoi(&ch_tab[i][1]);
							if (num_garage >= 0 && num_garage<NB_GARAGE_REEL && ch_nb == 5) {  // On vérifie qu'il y a bien les 5 arguments sur la ligne lue.
								i=i+2; continue;	// Si numéro de garage conforme, on continu, sinon on sort en erreur à la fin des tests.
							}
						}
					}
					// c1
					if(ch_nb-i>=1 && num_garage>=0 && num_garage<NB_GARAGE_REEL) {
						if( ch_tab[i][0]=='c') {
							if (atoi(&ch_tab[i][1])>=0 && atoi(&ch_tab[i][1])<(300+NB_CANTON) && (atoi(&ch_tab[i][1])%100)<NB_CANTON) {
								ass_canton[num_garage]=atoi(&ch_tab[i][1]);
								i++; continue;
							}
						}
					}
					// out3
					if(ch_nb-i>=1 && num_garage>=0 && num_garage<NB_GARAGE_REEL) {
						if(STR_SAME strncmp(ch_tab[i],"out",3) ) 	{
							if (atoi(&ch_tab[i][3])>=0 && atoi(&ch_tab[i][3])<(300+NB_OUT) && (atoi(&ch_tab[i][3])%100)<NB_OUT) {
								ass_out[num_garage]=atoi(&ch_tab[i][3]);
								i++; continue;
							}
						}
					}
					// pol1
					if(ch_nb-i>=1 && num_garage>=0 && num_garage<NB_GARAGE_REEL) {
						if(STR_SAME strncmp(ch_tab[i],"pol",3) ) 	{
							if (atoi(&ch_tab[i][3])==0 || atoi(&ch_tab[i][3])==1) {
								ass_out_pol[num_garage]=atoi(&ch_tab[i][3]);
								i++; continue;
							}
						}
					}
					strcpy(ch_error, "Fichier 'config.txt',\n\nSection #Garage,\n\nErreur de description sur la ligne :");
					for(i=0;i<ch_nb;i++) { strcat(ch_error,"  "); strcat(ch_error,ch_tab[i]); }
					MessageBox(NULL,ch_error,"UTS - Erreur dans 'config.txt'",MB_OK|MB_ICONERROR); exit(1);
				}  //fin groupe de mot
			}    //fin chaine
		}      //fin #garage
	}        //fin file
	moins_char_normal=1;
	fclose(pf);
}

//
void cGarage::save_conf(void)
{
	FILE* pf;
	int   i;  /*    int   i,j; */
	if((pf=fopen("debug_garage.txt","wt"))==NULL) {
		MessageBox(NULL,"Impossible de créer le fichier 'Debug_garage.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
	}
	for(i=0;i<NB_GARAGE;i++) {
		fprintf(pf,"\ngarage=%2d ass_canton=%3d ass_out=%3d num_train=%2d cmd_lock=%d state_lock=%d res_auto=%d",i, ass_canton[i], ass_out[i], ass_out_pol[i], numero_train[i], vio_garage_lock_cmd[i], vio_garage_lock_status[i], vio_garage_lock_res[i] );
	}
	fclose(pf);
}

//
void cGarage::maj(void)
{
	int i,cant,val;	/*     int i,cant,out,val; */
	garage_lock_and_unlock(); // Réalise le traitement de la demande de Raccordement/Isolation du garage en fonction des conditions.
	garage_lock_and_unlock(); // DEUX appels de suite à ctte fonction dés fois que l'on libére un garage et que l'on isole un garage sur le même canton, en même temps.
	                          // Avant cet appel était dans la boucle ci-dessous !
	for (i=0; i<NB_GARAGE; i++) {
		if (ass_canton[i]!=-1) { // = -1 ou Numéro de canton relié au garage (Garage en fonction).
			if (vio_garage_lock_status[i]) { // 1 => Le garage est isolé du canton (état réel).
				val=ass_out_pol[i];          // 0 ou 1 => Polarité de la commande du relais pour pour isoler le garage.
			}
			else {                    // 0 => Le garage est relié au canton (état réel).
				val=1-ass_out_pol[i]; // 0 ou 1 => Polarité de la commande du relais pour pour isoler le garage.
			}
			vio_out[ass_out[i]/100][ass_out[i]%100]=val; // ass_out[] = N° de variable = N° interne de 'out_xxx' => Active la sortie pour comander le relais d'isolation du garage.
		}
	}
}

// Affiche le tableau des garages à partir du menu principal.
// Affiche les garages des cartes 0-1 ou 2-3.
//
void cGarage::debug(int action)
{
	int i;
	int x,y,t;
	int garage_i, garage_j;
	char ch[200];
	static int garage_deb=0;
	int cur_ligne=0;
	static int dimx=60;		// Dimension verticale d'un cellule
	static int dimy=18;		// Dimension horizontale d'un cellule
	static int nblignes=NB_GARAGE_REEL;		// Nombre de lignes dans le tableau (sans le titre)

	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
	if(action==DEBUG_TOTAL_PAINT) {
		Rectangle(hMemDC,0,0,800,700);
		y=4*dimy;
		Rectangle(hMemDC,0,y,800,y+dimy+1);		// Dessine le rectangle autour des titres des colonnes.
		SelectObject(hMemDC,bmp_pinceau_gris192); SelectObject(hMemDC,bmp_stylo_gris192); Rectangle(hMemDC,800-15,15,800-2,2); // Rectangle gris pour fermer la fenêtre.
		SelectObject(hMemDC,bmp_stylo_noir); EasyLine(800-14,3,800-3,14 ); EasyLine(800-14,13,800-3,2); // Croix noire.
		SelectObject(hMemDC,bmp_stylo_noir);  EasyLine(800-2,1,800-2,16); EasyLine(800-16,15,800-1,15); // Trait noir.
		SelectObject(hMemDC,bmp_stylo_gris128); EasyLine(800-3,2,800-3,15); EasyLine(800-15,14,800-2,14); // Trait gris foncé.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

		SelectObject(hMemDC,bmp_fonte); SetBkMode(hMemDC,TRANSPARENT); SetTextColor(hMemDC,RGB(0,0,0)); // Texte noir
		EasyTextOut(2,2,"AFFICHE LES VALEURS NON NULLES DES PARAMÈTRES DES GARAGES   (16 maximum)"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		EasyTextOut(2,(nblignes+3)*dimy,"Section '#garage'");
		EasyTextOut(2,(nblignes+4)*dimy,"CLIQUEZ dans la colonne 'Cmd_I' pour relier ou isoler un garage au canton.");
		EasyTextOut(2,(nblignes+5)*dimy,"CnxCant  = Indication pour savoir si le garage est relié électriquement au canton.");
		EasyTextOut(2,(nblignes+6)*dimy,"Resv     = Canton réservé par un déplacement automatique.");
		EasyTextOut(2,(nblignes+7)*dimy,"Canton   = Numéro du canton connecté en sortie de garage.");
		EasyTextOut(2,(nblignes+8)*dimy,"N° Out   = Numéro de sortie utilisée pour commander le relais d'alimentation du garage au canton.");
		EasyTextOut(2,(nblignes+9)*dimy,"Polarité = Valeur de la sortie pour commander la connexion du garage au canton (Normale/Inverse).");

		EasyLine(1*dimx,dimy,1*dimx,dimy+dimy);		// Dessine les petits trais verticaux des titres des colonnes.
		EasyLine(2*dimx,dimy,2*dimx,dimy+dimy); 
		EasyLine(3*dimx,dimy,3*dimx,dimy+dimy); 
		EasyLine(4*dimx,dimy,4*dimx,dimy+dimy); 
		EasyLine(5*dimx,dimy,5*dimx,dimy+dimy); 
		EasyLine(6*dimx,dimy,6*dimx,dimy+dimy); 
		EasyLine(7*dimx,dimy,7*dimx,dimy+dimy); 
		EasyLine(2*dimx-10,dimy+dimy,2*dimx,dimy+dimy-10);  // Colonne 'Cmd_I' marquée '/' = valeurs modifiables.
		EasyLine(0,1*dimy,800,1*dimy);  // Ligne horizontale au dessus des titres.

		SetTextColor(hMemDC,RGB(255,0,0)); // Texte rouge
		EasyTextOut(0*dimx+5,2+1*dimy,"Garage");
		EasyTextOut(1*dimx+2,2+1*dimy," Cmd_I"); 
		EasyTextOut(2*dimx+2,2+1*dimy,"CnxCant");
		EasyTextOut(3*dimx+5,2+1*dimy," Resv"); 
		EasyTextOut(4*dimx+5,2+1*dimy,"Canton");
		EasyTextOut(5*dimx+5,2+1*dimy,"N° Out");
		EasyTextOut(6*dimx+2,2+1*dimy,"Polarit"); 
		EasyTextOut(7*dimx+5,2+1*dimy,"Train stationné  N° : Nom"); 
	}

	garage_deb=0; 	// N° du premier garage à afficher 

	if (action==DEBUG_MOUSE) { 	// ACTION = CLIC GAUCHE DE LA SOURIS
		if ((x_mouse > 800-15 && x_mouse < 800-2) && (y_mouse > 2 && y_mouse < 15)) {
			screen_mode= screen_mode_retour; 
			return;	// On ferme la fenêtre.
		}
		cur_ligne=(y_mouse-2*dimy)/dimy;
		if (cur_ligne>=0 && x_mouse>1*dimx && x_mouse<2*dimx && cur_ligne<16) {
			if (ass_canton[cur_ligne] != -1) {
				if (vio_garage_lock_res[cur_ligne] == 0) {  // 0 ou 1, 1 => Garage réservé.
					vio_garage_lock_cmd[cur_ligne] ^= 1;  // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
				}
			}
		}
	}

	if(action==DEBUG_MOUSE_RIGHT) { } // ACTION = CLIC DROIT DE LA SOURIS
	if(action==DEBUG_KEY)         { } // if(touche_char=='+') 

	SetTextColor(hMemDC,RGB(0,0,255)); // texte bleu
	for(i=0;i<nblignes;i++) { //
		y=dimy*(i+2);
		SelectObject(hMemDC,bmp_pinceau_blanc);
		garage_j=((i+garage_deb)/16);
		garage_i=((i+garage_deb)%16);
		if(garage_j>3) continue;
//vio_det[i] ) SelectObject(hMemDC,bmp_pinceau_jaune);

		Rectangle(hMemDC,0,y,800,y+dimy+1);
		EasyLine(1*dimx,y,1*dimx,y+dimy); // Dessine les traits verticaux.
		EasyLine(2*dimx,y,2*dimx,y+dimy); 
		EasyLine(3*dimx,y,3*dimx,y+dimy); 
		EasyLine(4*dimx,y,4*dimx,y+dimy); 
		EasyLine(5*dimx,y,5*dimx,y+dimy); 
		EasyLine(6*dimx,y,6*dimx,y+dimy); 
		EasyLine(7*dimx,y,7*dimx,y+dimy); 

		SelectObject(hMemDC,bmp_fonte); SetBkMode(hMemDC,TRANSPARENT); SetTextColor(hMemDC,RGB(0,0,255));

		x=0;   

		if (ass_canton[garage_deb+i]!=-1) {SetTextColor(hMemDC,RGB(0,0,255)); } // Texte bleu = garage valide
		else { SetTextColor(hMemDC,RGB(192,192,192)); }// Texte gris
		sprintf_s(ch,"%3d",100*garage_j+garage_i);
		EasyTextOut(x+10,y+3,ch);
		x+=dimx;
		if (vio_garage_lock_cmd[garage_deb+i]!=0) { // 0 ou 1, 1 => Demande d'isolation du garage (Sera réalisée si il a un train sur le canton).
			sprintf_s(ch,"%4d",vio_garage_lock_cmd[garage_deb+i]);
			EasyTextOut(x+2,y+3,ch);
		}
		x+=dimx;
		if (ass_canton[garage_deb+i]!=-1 ) {
			if (vio_garage_lock_status[garage_deb+i]==1) sprintf_s(ch," Isolé"); // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
			else sprintf_s(ch,"Relié");
			EasyTextOut(x+6,y+3,ch);
		}
		x+=dimx;
		if (vio_garage_lock_res[garage_deb+i]!=0) { // 0 ou 1, 1 => Garage réservé.
			sprintf_s(ch,"%4d",vio_garage_lock_res[garage_deb+i]);
			EasyTextOut(x+2,y+3,ch);
		}
		x+=dimx;
		if (ass_canton[garage_deb+i]!=-1) {
			if (vio_garage_lock_status[garage_deb+i]==0) sprintf_s(ch," %3d",ass_canton[garage_deb+i]); // 0 ou 1, 1 => Le garage est isolé du canton (état réel).
			else sprintf_s(ch,"(%3d)",ass_canton[garage_deb+i]);
			EasyTextOut(x+12,y+3,ch);
		}
		x+=dimx;
		if (ass_out[garage_deb+i]!=0) {
			sprintf_s(ch,"%4d",ass_out[garage_deb+i]); // Sortie pour commander le garage
			EasyTextOut(x+12,y+3,ch);
		}
		x+=dimx;
		if (ass_canton[garage_deb+i]!=-1 && ass_out_pol[garage_deb+i]!=0) { // Polarite
			sprintf_s(ch,"%4d",ass_out_pol[garage_deb+i]);
			EasyTextOut(x+2,y+3,ch);
		}
		x+=dimx;
		t=copy_garage_num_train[garage_deb+i];
		if (t!=-1) {
			sprintf_s(ch,"%4d : %s",t,copy_train_name[t]);
			EasyTextOut(x+2,y+3,ch);
			SelectObject(hMemDC,bmp_stylo_noir);
			bmp_select_brush(color_train[t]); // Affiche un rectangle de la couleur du train.
			Rectangle(hMemDC,x+132,y+5,x+144,y+13);
			SelectObject(hMemDC,bmp_pinceau_blanc);
			SelectObject(hMemDC,bmp_stylo_gris192);
		}
	}
}
