// UTS 2000 - Fichier 'canton.ccp' Gére les occupation, résérvation et libération des cantons
// V3.7c - Le 05/10/2016
/*****************************************************************************/
/* Début CANTON                                                               */
/*****************************************************************************/
#include  <windows.h>
#include  <string.h>
#include  <stdlib.h>
#include  <stdio.h>
#include  "Train_UTS.h"
#include  "canton.h"
#include  "train.h"
#include  "serial_port.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 bmp_select_brush(int no_color);
extern cSerialPort serialPort;


// Déclaration des variables externes
extern HBRUSH  bmp_pinceau_blanc,bmp_pinceau_jaune, bmp_pinceau_gris192,  bmp_pinceau_gris220;
extern HDC hMemDC;
extern HFONT     bmp_fonte;
extern HPEN      bmp_stylo_noir, bmp_stylo_gris128, bmp_stylo_gris192, bmp_stylo_blanc, bmp_stylo_jaune;
extern int moins_char_normal;   // 1: '- 'est un caractère normal (comme 0)  0: '-' est un séparateur (comme +)
extern int touche_char;
extern int copy_allowed_sens[NB_CARTE][NB_CANTON];
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 vio_canton_vit[NB_CARTE][NB_CANTON];        //UU: n'en garder qu'un et mettre en debug total
extern int vio_canton_vit_profil[NB_CARTE][NB_CANTON]; //UU: n'en garder qu'un et mettre en debug total
extern int vio_det[NB_CARTE][NB_CANTON];
extern int screen_mode;
extern int nb_selectif_lus;	// Pour connaitre le nombre de terme Cx:+- lus dans la partie '#selectif' de 'config.txt' 
                            // pour ne pas dépasser la limite de 100. (Faire +1 pour avoir le nombre).
extern int cfg_tempo_libe_cant; // 0 à 99 = Temporisation pour libérer un canton. Valeur lue dans 'config.txt'.
extern int x_mouse,y_mouse, screen_mode_retour;
extern int color_train[NB_TRAIN];
extern int det_elabore[NB_CARTE][NB_CANTON]; // 0-1, 1 = canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore.
extern int det_elaborep[NB_CARTE][NB_CANTON]; // 0-1, 1 = canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train > 0.
extern int det_elaborem[NB_CARTE][NB_CANTON]; // 0-1, 1 = canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train < 0.



//extern cTrain  train;
//
cCanton  canton;

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

//
cCanton::cCanton(void) { }

// Sous programme d'initialisation des variables utilisées pour les cantons.
//
void cCanton::init(void)
{
	int i,j;
	for(j=0; j<NB_CARTE; j++) for(i=0; i<NB_CANTON; i++) {
		        num_train[j][i]=-1;
		         res_auto[j][i]= 0; // Reservation en mode automatique pour tous les cantons du déplacement.
		  master_selectif[j][i]= 0; // ResvMANU = Canton reservé par le train en manuel. Le train est sur ce canton.
	master_selectif_tempo[j][i]= 0;
		     inv_selectif[j][i]= 0; // Bit canton inversé, après une boucle de retournement.
		  update_selectif[j][i]= 0; // Res2MANU = Prochain canton déjà reservé par le train en manuel. Le train est sera bientôt sur ce canton.
		         vit_auto[j][i]= 0; // Vitesse calculée des cantons en mode automatique pour tous les cantons du déplacement.
		     vit_selectif[j][i]= 0;
		     allowed_sens[j][i]= 3;	// bit poid 1 = sens + ,bit poid 2 = sens '-'
		copy_allowed_sens[j][i]= 3;	// bit poid 1 = sens + ,bit poid 2 = sens '-'
		      det_elabore[j][i]= 0; // 1= canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore.
		      det_elaborep[j][i]= 0; // 1= canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train > 0.
		      det_elaborem[j][i]= 0; // 1= canton occupé (avec temporisation), utilisé pour l'affichage des feux tricolore. Vitesse train < 0.
	}
}

// Sous programme de débugage. Appelé uniquement en cas d'activation de traces. Ecrit dans le fichier 'Debug_canton.txt'.
//
void cCanton::save_conf(void)
{
	FILE* pf;
	int   i,j;

	if((pf=fopen("debug_canton.txt","wt"))==NULL) {	// Ouverture du fichier.
		MessageBox(NULL,"Impossible de créer le fichier 'Debug_canton.txt'","Erreur",MB_OK|MB_ICONERROR); exit(1);
	}
	for(j=0;j<NB_CARTE;j++) for(i=0;i<NB_CANTON;i++) {	// Ecriture dans le fichier.
		fprintf(pf,"\nnum_train=%2d res_auto=%d master_sel=%d inv_sel=%d update_sel=%d",num_train[j][i],res_auto[j][i],master_selectif[j][i],inv_selectif[j][i],update_selectif[j][i]);
	}
	fclose(pf);
}

// Sous programme appelé cycliquement (tous les 80 ms en V3.3).
// On met à jour les variables "det2_xx" = det_elabore[NB_CARTE][NB_CANTON],  1 = canton occupé 
// (avec temporisation), utilisé pour l'affichage des feux tricolore pour éviter que les feux clignotent.
// Les leds des feux sont animés avec les variables "det2_xx" à la place des "det_xx.
//
void cCanton::maj(void)
{
	int i,j;
	for (j=0; j<NB_CARTE; j++) {
		for (i=0; i<NB_CANTON; i++) {
			vio_canton_vit[j][i]=0; // Vitesse sur les cantons = 0.
			if (res_auto[j][i]==0 && num_train[j][i]!=-1 && (master_selectif[j][i] || update_selectif[j][i])) vio_canton_vit[j][i]=vit_selectif[j][i];
			if (res_auto[j][i]==1) vio_canton_vit[j][i]=vit_auto[j][i];
			if (master_selectif_tempo[j][i] == 1 || master_selectif[j][i] == 1 || vio_det[j][i] == 1) det_elabore[j][i] = 1; else det_elabore[j][i] = 0;  // Modification en V3.6d, variables "det2_xx".
			if (det_elabore[j][i] == 1 && vio_canton_vit[j][i] > +3 ) det_elaborep[j][i] = 1; else det_elaborep[j][i] = 0;  // Modification en V3.6d, variables "det2p_xx".
			if (det_elabore[j][i] == 1 && vio_canton_vit[j][i] < -3 ) det_elaborem[j][i] = 1; else det_elaborem[j][i] = 0;  // Modification en V3.6d, variables "det2m_xx".
		}
	}
}

// Affiche le tableau des cantons à partir du menu : 'Debug > Cantons'.
// Affiche les cantons des cartes 0-1 ou 2-3.
// Cette fenêtre ne contient pas de données modifiables.
//
void cCanton::debug(int action)
{
	int i,j,y;
	int cant_i,cant_j;
	char ch[200];
	static int cant_deb=0;
	static int dimnx=44; // Dimension horizontal de la colonne 'Numéro'.
	static int dimcx=75; // Dimension horizontal des autres colonnes.
	static int dimy =16; // Dimension vertical d'une cellule.
	static int nblignes=32; // Nombre de ligne du tableau (sans le titre).
	static int decaly=16; //Decalage vers le bas de la premiére ligne du tableau.

	SelectObject(hMemDC,bmp_fonte); SetBkMode(hMemDC,TRANSPARENT);
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);

	if(action==DEBUG_TOTAL_PAINT) {     // ACTION = REDESSINE TOUTE LA FENETRE.
		Rectangle(hMemDC,0,0,800,700);
		SetTextColor(hMemDC,RGB(0,0,0));	// Texte en noir.
		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);
		EasyTextOut(2,2,"AFFICHE LES VALEURS NON NULLES DES PARAMÈTRES DES CANTONS"); EasyTextOut(800-140,2,"(QUITTER = ESC)");
		SelectObject(hMemDC,bmp_stylo_noir); SelectObject(hMemDC,bmp_pinceau_gris220); // Rectangle gris foncé.
		Rectangle(hMemDC,0,  decaly+(nblignes+1)*dimy+1-2+2, 97, decaly+(nblignes+2)*dimy+1-4+4);
		SelectObject(hMemDC,bmp_stylo_gris128);
		EasyLine(1,  decaly+(nblignes+2)*dimy+1-4+4-2, 96, decaly+(nblignes+2)*dimy+1-4+4-2);  	// Relief rectangle.
		EasyLine(95, decaly+(nblignes+1)*dimy+1-2+2+1, 95, decaly+(nblignes+2)*dimy+1-4+4-2);	// Relief rectangle.
		SelectObject(hMemDC,bmp_stylo_noir);
		EasyLine(97-10, decaly+(nblignes+2)*dimy+1-2-4+4, 97, decaly+(nblignes+2)*dimy+1-4-12+4);  // Dessine un trait dans l'angle = valeurs modifiables.
		SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		EasyTextOut(2,decaly+(nblignes+1)*dimy+2," CLIC-DROIT :AFFICHE LES PAGES 1<->2, [000-115]<->[200-315]");
		
		SetTextColor(hMemDC,RGB(255,0,0)); // Texte en rouge.
		EasyTextOut(              4,2+decaly,"Cant" );     // Numéro du canton
		EasyTextOut(4+dimnx+0*dimcx,2+decaly,"n° Train");  // Numéro du train (ou -1)
		EasyTextOut(4+dimnx+1*dimcx,2+decaly,"ResvAUTO");
		EasyTextOut(4+dimnx+2*dimcx,2+decaly,"Vit_AUTO");
		EasyTextOut(4+dimnx+3*dimcx,2+decaly,"ResvMANU");
		EasyTextOut(4+dimnx+4*dimcx,2+decaly,"Res2MANU");
		EasyTextOut(8+dimnx+5*dimcx,2+decaly,"Inversé");
		EasyTextOut(4+dimnx+6*dimcx,2+decaly,"Vit_MANU");
		EasyTextOut(8+dimnx+7*dimcx,2+decaly,"Vitesse");
		EasyTextOut(4+dimnx+8*dimcx,2+decaly,"Vit_réel");
		EasyTextOut(4+dimnx+9*dimcx,2+decaly,"Présence");   // Train détecté sur le canton.
		// Texte sous le tableau.
		SetTextColor(hMemDC,RGB(0,0,0)); // Texte en noir.
		EasyTextOut(2,decaly+(nblignes+2)*dimy+1,"ResvAUTO = 1 = Canton réservé par un déplacement en cours");
		EasyTextOut(2,decaly+(nblignes+3)*dimy+1,"Vit_AUTO     = Vitesse fixée par un déplacement en cours");
		EasyTextOut(2,decaly+(nblignes+4)*dimy+1,"ResvMANU = 1 = Canton principal en conduite manuelle");
		EasyTextOut(2,decaly+(nblignes+5)*dimy+1,"Res2MANU = 1 = Canton suivant en conduite manuelle");
		EasyTextOut(2,decaly+(nblignes+6)*dimy+1,"Inversé  = 1 = Suite à une boucle de retournement, la conduite du train est inversée");
		EasyTextOut(2,decaly+(nblignes+7)*dimy+1,"Vitesse      = Vitesse brute de consigne des cantons (-64, +64).");
		EasyTextOut(2,decaly+(nblignes+8)*dimy+1,"Vit_réel     = Vitesse des locomotives en fonction de leurs profils (Vmin,Vmax).");
		EasyTextOut(2,decaly+(nblignes+9)*dimy+1,"Temporisation libération des cantons '#balauto'+'tempo_libe_cant:' :"); 

		SetTextColor(hMemDC,RGB(0,0,255)); // Texte en bleu.
		sprintf_s(ch,"= %d => %d sec",cfg_tempo_libe_cant,cfg_tempo_libe_cant/10); 
		EasyTextOut(550,decaly+(nblignes+9)*dimy+1,ch);
		SetTextColor(hMemDC,RGB(0,0,0)); // Texte en noir.
	}

	if(action==DEBUG_MOUSE) {	// ACTION = CLIC GAUCHE DE LA SOURIS.
		if ((x_mouse > 0 && x_mouse < 97) && (y_mouse > decaly+(nblignes+1)*dimy+1-2+2 && y_mouse < decaly+(nblignes+2)*dimy+1-4+4)) { //	Clique dans [CLIC DROIT]
			action=DEBUG_MOUSE_RIGHT; //	Simule le clique-droit traité plus loin.
		}
		else {
			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.
			}
		}
	}

	if(action==DEBUG_MOUSE_RIGHT) {    // ACTION = CLIC DROIT DE LA SOURIS, on passe à la page suivante.
		Rectangle(hMemDC,0,decaly+dimy,dimnx+9*dimcx+1,decaly+(nblignes+1)*dimy+1);	// N'efface que la partie du tableau.
		if (cant_deb!=nblignes) screen_mode= MD_ECRAN_CANTON2;
		else                    screen_mode= MD_ECRAN_CANTON1;
	}

	if (screen_mode==MD_ECRAN_CANTON1) cant_deb=0;		// Premier numéro de cantons à afficher suivant la page affichée.
	if (screen_mode==MD_ECRAN_CANTON2) cant_deb=nblignes;

	if(action==DEBUG_KEY) { }          // ACTION = TOUCHE ENFONCEE
	
	SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_blanc);
	Rectangle(hMemDC,1, dimy+decaly, 799, (nblignes+1)*dimy+decaly+1);
	SelectObject(hMemDC,bmp_stylo_gris192);

	EasyLine(dimnx,decaly,dimnx,(nblignes+1)*dimy+decaly);// Trace la premiere ligne verticale à droite de la premiere colonne.
	// Trace les lignes verticales suivantes.
	for (i=0;i<11;i++) { EasyLine(dimnx+dimcx*i,decaly,dimnx+dimcx*i,(nblignes+1)*dimy+decaly);	}
	// Trace les lignes horizontales.
	for (i=0;i<nblignes+2;i++) { EasyLine(0,dimy*i+decaly,dimnx+10*dimcx,dimy*i+decaly); }
	y=0;
	SetTextColor(hMemDC,RGB(0,0,255));	// Texte en bleu.
	for(i=0;i<nblignes;i++) { // 32 lignes à l'écran.
		y=dimy*i+decaly+dimy;
		cant_j=((i+cant_deb)/16);  // cant_j = n° de carte.
		cant_i=((i+cant_deb)%16);  // cant_i = n° de canton. 
		if (cant_j==0 || (cant_j==1 && serialPort.card1_ok) || (cant_j==2 && serialPort.card2_ok) || (cant_j==3 && serialPort.card3_ok)) {
			 SetTextColor(hMemDC,RGB(0,0,255)); // En bleu si carte n°0 ou si connectée.
		}
		else  { SetTextColor(hMemDC,RGB(160,160,160)); } // En gris si carte <> n°0 et absente.
		if(cant_j>3) continue;
		Rectangle(hMemDC, dimnx,y,  dimnx+10*dimcx+1,  y+dimy+1);
		for (j=1;j<10;j++) { EasyLine(dimnx+j*dimcx,y,  dimnx+j*dimcx,  y+dimy+1);	}

													   sprintf_s(ch,"%4d",100*cant_j+cant_i);                  EasyTextOut(              5,y+2,ch);
		if (num_train[cant_j][cant_i]!=-1)           { sprintf_s(ch,"%6d",      num_train[cant_j][cant_i]);    EasyTextOut(2+dimnx+0*dimcx,y+2,ch);
 			SelectObject(hMemDC,bmp_stylo_noir); bmp_select_brush(color_train[num_train[cant_j][cant_i]]); // Affiche un rectangle de la couleur du train.
			Rectangle(hMemDC,2+dimnx+0*dimcx+56,y+5,2+dimnx+0*dimcx+12+56,y+5+8);
			SelectObject(hMemDC,bmp_pinceau_blanc); SelectObject(hMemDC,bmp_stylo_gris192);
		}
		if (res_auto[cant_j][cant_i]!=0)             { sprintf_s(ch,"%6d",       res_auto[cant_j][cant_i]);    EasyTextOut(2+dimnx+1*dimcx,y+2,ch);}
		if (vit_auto[cant_j][cant_i]!=0)             { sprintf_s(ch,"%6d",       vit_auto[cant_j][cant_i]);    EasyTextOut(2+dimnx+2*dimcx,y+2,ch);}
		if (master_selectif[cant_j][cant_i]!=0)      { sprintf_s(ch,"%6d",master_selectif[cant_j][cant_i]);    EasyTextOut(2+dimnx+3*dimcx,y+2,ch);}
		if (update_selectif[cant_j][cant_i]!=0)      { sprintf_s(ch,"%6d",update_selectif[cant_j][cant_i]);    EasyTextOut(2+dimnx+4*dimcx,y+2,ch);}
		if (inv_selectif[cant_j][cant_i]!=0)         { sprintf_s(ch,"%6d",   inv_selectif[cant_j][cant_i]);    EasyTextOut(2+dimnx+5*dimcx,y+2,ch);}
		if (vit_selectif[cant_j][cant_i]!=0)         { sprintf_s(ch,"%6d",   vit_selectif[cant_j][cant_i]);    EasyTextOut(2+dimnx+6*dimcx,y+2,ch);}
		if (vio_canton_vit[cant_j][cant_i]!=0)       { sprintf_s(ch,"%6d", vio_canton_vit[cant_j][cant_i]);    EasyTextOut(2+dimnx+7*dimcx,y+2,ch);}
		if (vio_canton_vit_profil[cant_j][cant_i]!=0){ sprintf_s(ch,"%6d",vio_canton_vit_profil[cant_j][cant_i]);EasyTextOut(2+dimnx+8*dimcx,y+2,ch);}
		if (vio_det[cant_j][cant_i]!=0)              { sprintf_s(ch,"%6d",        vio_det[cant_j][cant_i]);    EasyTextOut(2+dimnx+9*dimcx,y+2,ch);}
	}
}
/*****************************************************************************/
/* fin CANTON                                                                */
/*****************************************************************************/
