#include <string.h>
#include <stdio.h>
#include "pico/stdlib.h"

#include "ff.h"

#define TAILLE_TAMPON_LECTURE 10
#define TAILLE_TAMPON_ECRITURE 0x8000

struct tampon_ecriture_t{
    char tampon0[TAILLE_TAMPON_ECRITURE], tampon1[TAILLE_TAMPON_ECRITURE];
    char * tampon_a_ecrire, *tampon_actif;
    unsigned int index_tampon, taille_tampon_a_ecrire;
    FIL fp;
} tampon_event, tampon_telemetrie;



void ecrit_tampon_dans_sd(struct tampon_ecriture_t * tampon_ecriture){
    if(tampon_ecriture->tampon_a_ecrire != NULL){
        absolute_time_t current_time, start_time;
        unsigned int nb_ecrit;
        start_time = get_absolute_time();
        f_write(&tampon_ecriture->fp, tampon_ecriture->tampon_a_ecrire, tampon_ecriture->taille_tampon_a_ecrire,  &nb_ecrit);
        f_sync(&tampon_ecriture->fp);
        current_time = get_absolute_time();
        printf(">sd(Mo/s):%d:%.3f\n", (int)(current_time/1000), (float)(nb_ecrit) / (float)(current_time - start_time));
        //printf(">Octets:%d:%d\n", (int)(current_time/1000), nb_ecrit);
        //printf(">temps_sd:%d:%lld\n", (int)(current_time/1000), current_time - start_time);
        tampon_ecriture->tampon_a_ecrire = NULL;
    }

}

void routine_log_sd(void){
    while(1){
        ecrit_tampon_dans_sd(&tampon_event);
        ecrit_tampon_dans_sd(&tampon_telemetrie);
        sleep_ms(10);
    }
};

void ajout_texte_a_tampon(const char *chaine, struct tampon_ecriture_t * tampon_ecriture){
    if(tampon_ecriture->index_tampon + strlen(chaine) > TAILLE_TAMPON_ECRITURE){
        tampon_ecriture->tampon_a_ecrire = tampon_ecriture->tampon_actif;
        // permutation du tampon actif
        // indication du tampon à écrire
        // remise à 0 de l'index du tampon
        if(tampon_ecriture->tampon_actif == tampon_ecriture->tampon0){
            tampon_ecriture->tampon_actif = tampon_ecriture->tampon1;
            tampon_ecriture->tampon_a_ecrire = tampon_ecriture->tampon0;
        }else{
            tampon_ecriture->tampon_actif = tampon_ecriture->tampon0;
            tampon_ecriture->tampon_a_ecrire = tampon_ecriture->tampon1;
        }
        tampon_ecriture->taille_tampon_a_ecrire = tampon_ecriture->index_tampon;
        tampon_ecriture->index_tampon = 0;
        tampon_ecriture->tampon_actif[0] = 0;
    }
    strcat(tampon_ecriture->tampon_actif, chaine);
    tampon_ecriture->index_tampon += strlen(chaine);
    ecrit_tampon_dans_sd(tampon_ecriture);
}

void init_tampon_ecriture( struct tampon_ecriture_t * tampon_ecriture ){
    tampon_ecriture->tampon_actif = tampon_ecriture->tampon0;
    tampon_ecriture->index_tampon = 0;
    tampon_ecriture->tampon_a_ecrire = NULL;
    tampon_ecriture->tampon0[0];
    tampon_ecriture->tampon1[0];
}

char * get_tampon_inactif(struct tampon_ecriture_t * tampon_ecriture){
    if(tampon_ecriture->index_tampon){
        return tampon_ecriture->tampon0;
    }
    return tampon_ecriture->tampon1;
}

char * get_tampon_actif(struct tampon_ecriture_t * tampon_ecriture){
    if(tampon_ecriture->index_tampon){
        return tampon_ecriture->tampon0;
    }
    return tampon_ecriture->tampon1;
}

void log_message(const char * message, struct tampon_ecriture_t * tampon_ecriture);

int log_running = 0;


void erreur(char * message){
    while(1){
        puts(message);
        sleep_ms(100);
    }
}

void log_init(const char * drive_path){
    FIL fp;
    FRESULT result;
    uint16_t num_log;
    unsigned int nb_lu;
    char message_erreur[150];
    char tampon[TAILLE_TAMPON_LECTURE];

    // Ouverture de num_log.txt
    char path_num_log[20], path[30];
    strcpy(path_num_log, drive_path);
    strcat(path_num_log, "/num_log.txt");
    result = f_open(&fp, path_num_log, FA_OPEN_EXISTING | FA_READ);
    num_log = 0;
    if(!result){
        // le fichier existe, lisons-le 
        result = f_read (&fp, tampon, TAILLE_TAMPON_LECTURE, &nb_lu);
        if(!result){
            // lisons le nombre dans le tampon
            for(int index = 0; index < TAILLE_TAMPON_LECTURE; index++){
                if(tampon[index] >= '0' && tampon[index] <= '9'){
                    num_log = num_log * 10 + tampon[index] - '0';
                }else{
                    break;
                }
            }
            num_log++;
        }else{
            sprintf(message_erreur, "Échec à la lecture du fichier %s: %d", path_num_log, result);
            erreur(message_erreur);
        }
    }
    f_close(&fp);
    // Écriture de num_log dans num_log.txt
    sprintf(tampon, "%d\n", num_log);
    printf("%s", tampon);
    result = f_open(&fp, path_num_log, FA_CREATE_ALWAYS | FA_WRITE);
    if(!result){
        result = f_write(&fp, tampon, strlen(tampon),  &nb_lu);
        if(result){
            sprintf(message_erreur, "Échec à l'écriture du fichier %s: %d", path_num_log, result);
            erreur(message_erreur);
        }
    }else{
        sprintf(message_erreur, "Échec à l'ouverture du fichier %s: %d", path_num_log, result);
        erreur(message_erreur);
    }
    f_close(&fp);
    
    printf("num_log:%d\n", num_log);


    init_tampon_ecriture(&tampon_event);
    init_tampon_ecriture(&tampon_telemetrie);

    // Ouverture du fichier de log
    sprintf(path, "%s%s%03d.txt", drive_path, "data", num_log);
    printf("path: %s\n", path);
    result = f_open(&(tampon_telemetrie.fp), path, FA_CREATE_ALWAYS | FA_WRITE);
    if(result){
        sprintf(message_erreur, "Échec à l'ouverture du fichier %s: %d", path, result);
        erreur(message_erreur);
    }
    result = f_write(&(tampon_telemetrie.fp), "Début du fichier\n", strlen("Début du fichier"),  &nb_lu);
    f_sync(&(tampon_telemetrie.fp));
    printf("Fichier créé: %s\n", path);
    
    // Ouverture du fichier de telemetrie
    sprintf(path, "%s%s%03d.txt", drive_path, "event",  num_log);
    result = f_open(&(tampon_event.fp), path, FA_CREATE_ALWAYS | FA_WRITE);
    result |= f_write(&(tampon_event.fp), "Début du fichier\n", strlen("Début du fichier"),  &nb_lu);
    if(result){
        sprintf(message_erreur, "Échec à l'ouverture du fichier %s: %d", path, result);
        erreur(message_erreur);
    }
    printf("Fichier créé: %s\n", path);


    log_running = 1;
    

}

void log_telemetrie(char * message){
    log_message(message, &tampon_telemetrie);
}

void log_event(char * message){
    log_message(message, &tampon_event);
    
}

void log_message(const char * message, struct tampon_ecriture_t * tampon_ecriture){
    if(log_running){
        absolute_time_t current_time;
        char temps[20];
        
        current_time = get_absolute_time();
        
        sprintf(temps, "%lld:", current_time);
        ajout_texte_a_tampon(temps, tampon_ecriture);
        ajout_texte_a_tampon(message, tampon_ecriture);
    }
}

