/**
 * @file gestionFichier.h
 * @brief Contients les fonctions de gestions des fichiers.
 * @author Valentin PORTAIL et Jérémie VILLEPREUX
 * @version 1.0
 * @date 08/11/2022
 */

#include "interpolation.h"
#include "gestionFichier.h"
#include "approximation.h"



/** 
 * @brief Permet de creer une matrice de double.
 *
 * @param[in] n      Nombre de ligne de la matrice à créer. 
 * @param[in] m      Nombre de colonne de la matrice à créer.
 *
 * @return Renvoie un pointeur sur la première case de la matrice.
 */
double **matrice(unsigned int n,  unsigned int m){

    unsigned int i,j;
    double**matrice=NULL;

    matrice=(double **)malloc(n*sizeof(double *));

    if (!matrice){
	perror("Allocation fail.\n");
	return NULL;
    }
	
    for(i=0; i<n; ++i){
	matrice[i]=(double*)malloc(m*sizeof(double));
		
	if (!matrice[i]){
	    for(j=0; j<i; ++j){
		free(matrice[i]);
		matrice[i]=NULL;
	    }
	    free(matrice);
	    matrice=NULL;
	    perror("Allocation fail.\n");
	    return NULL;
 
	}
    }
    return matrice;
}



/** 
 * @brief Procédure qui permet de libérer une matrice.
 *
 * @param[in] n      Nombre de ligne de la matrice à créer. 
 *
 */
void freeMat(double **tab, unsigned int n){
    
    if(tab){
	unsigned int i=0;

	for(i=0; i<n; i++){
	    if (!tab[i]){
		free(tab[i]);
		tab[i] =NULL;	
	    }
	}
	free(tab);
	tab = NULL;
    }
}


/** 
 * @brief Permet d'ouvrir un fichier.
 *
 * @param[in] nom_fichier      Chaine de caractère désignant le nom fichier. 
 * @param[in] mode             Chaine de caractère désignant le mode d'ouverture du fichier.
 *
 * @return Renvoie le descripteur du fichier (pointeur).
 */
FILE * ouvertureFichier(char * nom_fichier, char * mode){
    
    FILE * f = NULL;
    f = fopen(nom_fichier, mode);

    if (!f) {
	perror("Problème d'ouverture de fichier");
        exit(EXIT_FAILURE);
    }
    return f;
}

/** 
 * @brief Procédure permettant de fermer un fichier.
 *
 * @param[in] descripteur       Descripteur de fichier
 *
 */
void fermetureFichier(FILE * descripteur){
    
    if (descripteur) fclose(descripteur);
}


/** 
 * @brief Permet de lire les points d'un fichier test et d'écrire dans un
 * tableau les résulats.
 *
 * @param[in] nom_fichier      Chaine de caractère désignant le nom fichier. 
 * @param[in] nb_points             Nombrede points dans un fichier.
 *
 * @return Renvoie un pointeur sur la première case de la matrice contenant les points.
 */
double ** lecture_points(char * nom_fichier, unsigned int nb_points) {

    FILE * f=NULL;
    double ** points = NULL;
    unsigned int i;
    double x, y;
    

    f = ouvertureFichier(nom_fichier, "r");
    points=matrice(nb_points, 2);

    /* --DEBUT LECTURE-- */
    for (i = 0; i < nb_points; ++i) {
        fscanf(f, "%lf%lf", &x, &y);
        points[i][0] = x;
        points[i][1] = y;

	//Rappel des points lus
        printf("%lf | %lf\n", x, y);
    }
    /* --FIN LECTURE-- */

    fermetureFichier(f);

    return points;
}



/** 
 * @brief Permet de lire les points d'un fichier test et d'écrire dans un
 * tableau les résulats.
 *
 * @param[in] nom_fichier      Chaine de caractère désignant le nom fichier. 
 * @param[in] num_col          Numero de colonne dans laquelle lire.
 * @param[in] nb_points        Nombre de points dans un fichier.
 *
 * @return Renvoie un pointeur sur la première case de la matrice contenant les points.
 */
float *lecture_colonne(char * nom_fichier, int num_col, int nb_points){
    
    FILE * f=NULL;
    float *points = NULL;
    int i;
    float x, y;

    f = ouvertureFichier(nom_fichier, "r");
    
    points = malloc(sizeof(float)*nb_points);

    if (!points){
	perror("Allocation failure.\n");
	exit(EXIT_FAILURE);
    }
    
    /* --DEBUT LECTURE-- */
    for (i = 0; i < nb_points; ++i) {

	
        fscanf(f, "%f %f\n", &x, &y);

	if (num_col==1){
	    points[i] = y;
	}
        else if (num_col==0){
		points[i] = x;
	    }

    }
    /* --FIN LECTURE-- */

    fermetureFichier(f);

    return points;
    
}

/** 
 * @brief Procédure qui permet d'ajouter deux poitns dans un fichier (à la fin).
 *
 * @param[in] nom_fichier   Chaine de caractère désignant le nom fichier. 
 * @param[in] x             Valeur à écrire.
 * @param[in] y             Valeur à écrire.
 *
 */
void ecriture_points(char * nom_fichier, double x, double y) {

    FILE * f=NULL;

    f = ouvertureFichier(nom_fichier, "a");
    fprintf(f, "%lf %lf\n", x, y);
    fermetureFichier(f);
}


/** 
 * @brief Procédure qui permet d'ajouter deux poitns dans un fichier (à la fin),
 * ces deux points sont stockés dans un tabeau.
 *
 * @param[in] nom_fichier   Chaine de caractère désignant le nom fichier. 
 * @param[in] tab           tableau des deux points à écrire.
 *
 */
void ecriture_points_approx(char * nom_fichier, float *tab) {

    FILE * f=NULL;

    f = ouvertureFichier(nom_fichier, "a");
    fprintf(f, "%lf %lf\n", tab[0], tab[1]);
    if (!strcmp(nom_fichier, "polynome4_A.txt")){
	printf("Le polynome qui approxime au mieux le polynôme est : %fx**(%f).\n", tab[1], tab[0]);
    }
    else {
	printf("Le polynome qui approxime au mieux le polynôme est : %f*x + %lf.\n", tab[0], tab[1]);	
    }

    fermetureFichier(f);
    libere_tab_1d(tab);
}





/** 
 * @brief Fonction qui permet de libérer, un tableau de double.
 *
 * @param[in] points          Tableau des nombres de points à liberer. 
 * @param[in] nb_points       Nombre de ligne de la matrice.
 *
 */
int liberation_points(double ** points, unsigned int nb_points){
    
    unsigned int i;

    for (i = 0; i < nb_points; ++i){
	    free(points[i]);
	    points[i] = NULL;
    }

    free(points);
    points = NULL;

    return EXIT_SUCCESS;
}


