
/*! 
	\file quatre.c
	\author GOIGOUX Lucie & JEUDI--LEMOINE Alix
	\date 12/01/23
	\brief Partie 4 de la SAE 1.02

	Application de gestion des candidature dans les IUT de France
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <strings.h> // strcasecmp : insensitive case
#include <unistd.h> // access : vérifier si fichier existe
#include "quatre.h"


void menuCandidat_suivreCandidature(ListeCandidats liste, int nbCandidats, Candidat* candidat) {
	int i, j, k, mustReply = 0, nbPropositions = 0;
	char reponse1, reponse2, poubelle;
	FileAttente* file;
	CandidatTraite* candidatAdmis = (CandidatTraite*) malloc(sizeof(CandidatTraite));
	ListeCandidatures listeCandidatures;

	if(candidatAdmis == NULL) {
		perror("malloc");
		exit(errno);
	}

	// Création d'une liste qui va contenir les candidatures pour lesquelles le candidat a été accepté
	// (pour le moment, seul une proposition peut être faite étant donné que seul le département Informatique de Clermont-Ferrand est habilité à donner une réponse)
	ListeCandidatures propositions = (ListeCandidatures) malloc(candidat->nbCandidatures*sizeof(Candidature*));

	if(propositions == NULL) {
		perror("malloc");
		exit(errno);
	}

	if(candidat->nbCandidatures == 0)
		fprintf(stderr, "\e[0;91mErreur : vous n'avez aucune candidature en cours, merci de réessayer plus tard.\n\e[0m");
	else
		afficherCandidatures(candidat->listeCandidatures, candidat->nbCandidatures);

	for(i=0; i<candidat->nbCandidatures; i++)
		if(candidat->listeCandidatures[i]->decision == 1 && candidat->listeCandidatures[i]->validation == 0) {
			mustReply = 1;
			propositions[nbPropositions++] = candidat->listeCandidatures[i];
		}
	
	if(mustReply == 1) {
		printf("Vous avez %d candidature(s) contenant une proposition d'admission, souhaitez-vous y répondre ? (O/N) : ", nbPropositions);
		scanf("%*c%c", &reponse1);

		for(i=0; i<nbPropositions; i++) {
			if(reponse1 == 'o' || reponse1 == 'O') {
				afficherCandidatures(propositions+i, 1);

				printf("\nSouhaitez-vous accepter ou refuser cette proposition ? (A/R) : ");
				scanf("%*c%c", &reponse2);
				
				if(reponse2 == 'a' || reponse2 == 'A'){
					printf("\n\e[1;32mProposition pour le département '%s' à l'IUT '%s' acceptée !\e[0m\n",
						   propositions[i]->departement, propositions[i]->ville);

					for(j=0; j<candidat->nbCandidatures; j++) {
						candidat->listeCandidatures[j]->decision = -1;
						candidat->listeCandidatures[j]->validation = -1;
					}

					propositions[i]->decision = 1;
					propositions[i]->validation = 1;

					break;
				} else {
					if(reponse2 == 'r' || reponse2 == 'R') {
						printf("\n\e[1;32mProposition pour le département '%s' à l'IUT '%s' refusée !\e[0m\n",
							   propositions[i]->departement, propositions[i]->ville);

						propositions[i]->validation = -1;

						file = lireCandidatsAttente(propositions[i]->departement, propositions[i]->ville);
						*candidatAdmis = defiler(file);
						ecrireCandidatsAttente(propositions[i]->departement, propositions[i]->ville, file);
						ajouterCandidatAdmis(propositions[i]->departement, propositions[i]->ville, candidatAdmis);

						if(strcmp(candidatAdmis->nom, "") != 0 && strcmp(candidatAdmis->prenom, "") != 0) {
							for(j=0; j<nbCandidats; j++) {
								if(strcmp(liste[j]->nom, candidatAdmis->nom) == 0
								   && strcmp(liste[j]->prenom, candidatAdmis->prenom) == 0) {
									listeCandidatures = liste[j]->listeCandidatures;
									for(k=0; k<liste[j]->nbCandidatures; k++)
										if(listeCandidatures[k]->ville == propositions[i]->ville 
										   && listeCandidatures[k]->departement == propositions[i]->departement) {
											listeCandidatures[k]->decision = 1;
											break;
										   }
								}
							}
						}
					} else {
						while ((poubelle = getchar()) != '\n' && poubelle != EOF);
						fprintf(stderr, "\n\e[0;91mErreur : la réponse saisie est incorrecte. Merci de réessayer plus tard.\n\e[0m");
						break;
					}
				}
			} else {
				if(reponse1 == 'n' || reponse1 == 'N')
					printf("\n\t\e[1mTrès bien. Vous pouvez toujours donner votre réponse ultérieurement.\e[0m\n");
				else {
					while ((poubelle = getchar()) != '\n' && poubelle != EOF);
					fprintf(stderr, "\n\e[0;91mErreur : la réponse saisie est incorrecte. Merci de réessayer plus tard.\n\e[0m");
					break;
				}
			}
		}
	}

	free(propositions);
	free(candidatAdmis);
}

void menuResponsable_traiterCandidatures(VilleIUT** tiut, int nbVilles, ListeCandidats liste, int nbCandidats) {
	char dept[LEN_MAX], ville[LEN_MAX], choix, poubelle;
	int nbCandidatsAccept, pos, verif, checkQueue = 0;
	ListeDept ldept;

	strcpy(dept, "Informatique");
	strcpy(ville, "Clermont-Ferrand");

	printf("\n\e[3;32mLes deux prochaines lignes sont affichées à titre informatif\e[0m\n\n");
	printf("Entrez le nom de la ville que vous souhaitez traiter : %s\n", ville);
	printf("Quel département souhaitez-vous modifier ? : %s\n", dept);

	printf("\n\e[1;32mTraitement des candidatures pour le département '%s' de l'IUT '%s'\n\n\e[0m", dept, ville);

	printf("Combien de candidats souhaitez-vous accepter ? : ");
	if(scanf("%d", &nbCandidatsAccept) == 0) {
		while ((poubelle = getchar()) != '\n' && poubelle != EOF);
		fprintf(stderr, "\n\e[0;91mErreur : la valeur entrée est invalide, merci de réessayer plus tard.\n\n\e[0m");
		return;
	}

	pos = rechercherVille(tiut, nbVilles, ville);

	ldept = tiut[pos]->ldept;

    while(ldept != NULL && strcmp(ldept->departement, dept) != 0)
        ldept = ldept->suiv;

    if(ldept->noteMinimale == -1) {
		printf("\n\e[1;91mAttention, après avoir entré cette valeur, elle ne sera plus modifiable !\e[0m\n\nQuelle est la note minimale pour l'acception du candidat ? : ");
		verif = scanf("%f", &ldept->noteMinimale);
		while((ldept->noteMinimale) < 0 || (ldept->noteMinimale) > 20 || verif == 0) {
			fprintf(stderr, "\e[0;91mLa note entrée est incorrecte\n\e[0mEntrez une note minimale entre 0 et 20 : ");
			verif = scanf("%f", &ldept->noteMinimale);
		}
    } else {
		checkQueue = 1;
	}

	printf("\nMerci de confirmer : Il faut accepter %d candidat avec une note minimale de %.2f (O/N) ? : ", nbCandidatsAccept, ldept->noteMinimale);

	scanf("%*c%c", &choix);

	if(choix == 'n' || choix == 'N')
		printf("\n\e[1mAnnulation de l'opération.\e[0m\n\n");
	else
		if(choix == 'o' || choix == 'O')
			traiterCandidatures(liste, nbCandidats, nbCandidatsAccept, ldept->noteMinimale, checkQueue);
		else {
			while ((poubelle = getchar()) != '\n' && poubelle != EOF);
			fprintf(stderr, "\n\e[0;91mErreur : la valeur entrée est invalide, merci de réessayer plus tard.\n\n\e[0m");		
		}

}

FileAttente* creerFile(void) {
	FileAttente* file = (FileAttente*) malloc(sizeof(FileAttente));

	if(file == NULL) {
		perror("malloc");
		exit(errno);
	}

    file->tete = NULL;
    file->queue = NULL;
	file->nbAttente = 0;

	return file;
}

int estVide(FileAttente *file) {
    return file->tete == NULL;
}

void enfiler(FileAttente *file, CandidatTraite candidat) {
    Maillon* nouveauMaillon = (Maillon*) malloc(sizeof(Maillon));
    nouveauMaillon->candidat = candidat;
    nouveauMaillon->suivant = NULL;

    if (estVide(file))
		file->tete = nouveauMaillon;
	else
        file->queue->suivant = nouveauMaillon;

	file->queue = nouveauMaillon;
}

CandidatTraite defiler(FileAttente *file) {
	CandidatTraite candidat = {"", "", 0, 0, 0, 0, 0};
	Maillon *tete;

    if (!estVide(file)) {
        tete = file->tete;

        candidat = tete->candidat;
        file->tete = tete->suivant;
		file->nbAttente = file->nbAttente-1;
        free(tete);
    }
	
	return candidat;
}

FileAttente* lireCandidatsAttente(char* dept, char* ville) {
	FileAttente* fileCandidats = creerFile();
	CandidatTraite candidat;
	int i;

	char fNameAttente[100];

	strcpy(fNameAttente, "donnees/");
    strcat(fNameAttente, ville);
    strcat(fNameAttente, "_");
    strcat(fNameAttente, dept);
    strcat(fNameAttente, "_Attente.don");

	if(access(fNameAttente, F_OK) != -1) {
		FILE *fAttente = fopen(fNameAttente, "r");

		if(fAttente == NULL) {
			perror("fopen");
			exit(errno);
		}

		fscanf(fAttente, "%d\n", &fileCandidats->nbAttente);

		for(i=0; i<fileCandidats->nbAttente; i++) {
			fscanf(fAttente, "%[^\n]\n%[^\n]\n%f %f %f %f %f\n",
				candidat.nom, candidat.prenom, &candidat.moyenneMath, &candidat.moyenneFrancais,
				&candidat.moyenneAnglais, &candidat.moyenneSpecialite, &candidat.noteGlobale);

			enfiler(fileCandidats, candidat);
		}

		fclose(fAttente);
	}

	return fileCandidats;
}

void ecrireCandidatsAttente(char* dept, char* ville, FileAttente* file) {
	Maillon* parcourir = file->tete;
	char fNameAttente[100];

	strcpy(fNameAttente, "donnees/");
    strcat(fNameAttente, ville);
    strcat(fNameAttente, "_");
    strcat(fNameAttente, dept);
    strcat(fNameAttente, "_Attente.don");

	FILE *fAttente = fopen(fNameAttente, "w");

	if(fAttente == NULL) {
		perror("fopen");
		exit(errno);
	}

	if(file->nbAttente > 0)
		fprintf(fAttente, "%d\n", file->nbAttente);

	while(parcourir != NULL) {
		fprintf(fAttente, "%s\n%s\n%f %f %f %f %f\n",
			parcourir->candidat.nom, parcourir->candidat.prenom, parcourir->candidat.moyenneMath, parcourir->candidat.moyenneFrancais,
			parcourir->candidat.moyenneAnglais, parcourir->candidat.moyenneSpecialite, parcourir->candidat.noteGlobale);

		parcourir = parcourir->suivant;
	}

	fclose(fAttente);
}


int compareCandidatsTraite(const void* p1, const void* p2) {
    CandidatTraite* c1 = *(ListeAdmis) p1;
    CandidatTraite* c2 = *(ListeAdmis) p2;

    char nomComplet1[60];
    strcpy(nomComplet1, c1->nom);
    strcat(nomComplet1, c1->prenom);

    char nomComplet2[60];
    strcpy(nomComplet2, c2->nom);
    strcat(nomComplet2, c2->prenom);

    return strcmp(nomComplet1, nomComplet2);
}

void ajouterCandidatAdmis(char* dept, char* ville, CandidatTraite* candidat) {
	ListeAdmis liste;
	int nbAdmis, i;

	char fNameAdmis[100];

	strcpy(fNameAdmis, "donnees/");
    strcat(fNameAdmis, ville);
    strcat(fNameAdmis, "_");
    strcat(fNameAdmis, dept);
    strcat(fNameAdmis, "_Admis.don");

	FILE *fAdmis = fopen(fNameAdmis, "r");

	if(fAdmis == NULL) {
		perror("fopen");
		exit(errno);
	}

	fscanf(fAdmis, "%d\n", &nbAdmis);

	liste = (ListeAdmis) malloc((nbAdmis+1)*sizeof(CandidatTraite*));

	if(liste == NULL) {
		perror("malloc");
		exit(errno);
	}

	for(i=0; i<nbAdmis; i++) {
		liste[i] = (CandidatTraite*) malloc(sizeof(CandidatTraite));

		if(liste[i] == NULL) {
			perror("malloc");
			exit(errno);
		}

		fscanf(fAdmis, "%[^\n]\n%[^\n]\n%f %f %f %f %f\n",
			liste[i]->nom, liste[i]->prenom, &liste[i]->moyenneMath, &liste[i]->moyenneFrancais,
			&liste[i]->moyenneAnglais, &liste[i]->moyenneSpecialite, &liste[i]->noteGlobale);
	}

	fclose(fAdmis);

	fAdmis = fopen(fNameAdmis, "w");

	if(fAdmis == NULL) {
		perror("fopen");
		exit(errno);
	}

	nbAdmis += 1;
	liste[nbAdmis-1] = candidat;

	fprintf(fAdmis, "%d\n", nbAdmis);

	for(i=0; i<nbAdmis; i++) {
		fprintf(fAdmis, "%s\n%s\n%f %f %f %f %f\n",
			liste[i]->nom, liste[i]->prenom, liste[i]->moyenneMath, liste[i]->moyenneFrancais,
			liste[i]->moyenneAnglais, liste[i]->moyenneSpecialite, liste[i]->noteGlobale);
	}
	
	fclose(fAdmis);
	free(liste);
}

void afficherCandidatsAdmis(char* dept, char* ville) {
	ListeAdmis liste;
	int nbAdmis, i;

	char fNameAdmis[100];

	strcpy(fNameAdmis, "donnees/");
    strcat(fNameAdmis, ville);
    strcat(fNameAdmis, "_");
    strcat(fNameAdmis, dept);
    strcat(fNameAdmis, "_Admis.don");

	if(access(fNameAdmis, F_OK) != -1) {
		FILE *fAdmis = fopen(fNameAdmis, "r");

		if(fAdmis == NULL) {
			perror("fopen");
			exit(errno);
		}

		fscanf(fAdmis, "%d\n", &nbAdmis);

		liste = (ListeAdmis) malloc(nbAdmis*sizeof(CandidatTraite*));

		if(liste == NULL) {
			perror("malloc");
			exit(errno);
		}

		for(i=0; i<nbAdmis; i++) {
			liste[i] = (CandidatTraite*) malloc(sizeof(CandidatTraite));

			if(liste[i] == NULL) {
				perror("malloc");
				exit(errno);
			}

			fscanf(fAdmis, "%[^\n]\n%[^\n]\n%f %f %f %f %f\n",
				liste[i]->nom, liste[i]->prenom, &liste[i]->moyenneMath, &liste[i]->moyenneFrancais,
				&liste[i]->moyenneAnglais, &liste[i]->moyenneSpecialite, &liste[i]->noteGlobale);
		}
		
		qsort(liste, nbAdmis, sizeof(CandidatTraite*), compareCandidatsTraite);

		for(i=0; i<nbAdmis; i++) {
			printf("\e[4;37mCandidat '%s %s' :\e[0m"
				"\n  - Moyenne en mathématiques : %.2f\n  - Moyenne en français : %.2f"
				"\n  - Moyenne en anglais : %.2f\n  - Moyenne en spécialité : %.2f"
				"\n  - Note globale attribuée : %.2f\n\n",
				liste[i]->nom, liste[i]->prenom, liste[i]->moyenneMath, liste[i]->moyenneFrancais,
				liste[i]->moyenneAnglais, liste[i]->moyenneSpecialite, liste[i]->noteGlobale);
		}

		fclose(fAdmis);
		free(liste);
	} else
		fprintf(stderr, "\n\e[1;91mErreur : les candidatures n'ont pas encore été traitées, merci de réessayer plus tard.\n\n\e[0m");

}

void afficherCandidatsAttente(FileAttente* file) {
	int i=0;
	Maillon* parcourir = file->tete;

	if(!estVide(file))
		while(parcourir != NULL) {
			printf("\e[4;37mCandidat '%s %s' (position %d/%d) :\e[0m"
				   "\n  - Moyenne en mathématiques : %.2f\n  - Moyenne en français : %.2f"
				   "\n  - Moyenne en anglais : %.2f\n  - Moyenne en spécialité : %.2f"
				   "\n  - Note globale attribuée : %.2f\n\n",
				   parcourir->candidat.nom, parcourir->candidat.prenom, ++i, file->nbAttente, parcourir->candidat.moyenneMath, parcourir->candidat.moyenneFrancais,
				   parcourir->candidat.moyenneAnglais, parcourir->candidat.moyenneSpecialite, parcourir->candidat.noteGlobale);
			parcourir = parcourir->suivant;
		}
	else
		fprintf(stderr, "\n\e[1;91mErreur : les candidatures n'ont pas encore été traitées ou aucun candidat n'est en attente, merci de réessayer plus tard.\n\n\e[0m");

}