#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <stdlib.h>

#include "opts.h"

char *get_str_help()
{
    static char str_help[] =
        "Options :\n"
        "[--in|-i {nom fichier entrée}]\n"
        "    Nom du fichier de entrée\n"
        "[--out|-o {nom fichier sortie}]\n"
        "    Nom du fichier de sortie\n"
        "[--help | -h]\n"
        "    Help = afficher l'aide\n"
        "[--quiet | -q]\n"
        "    Mode silencieux (sauf si erreur critique).\n";
    return str_help;
}

int valide_nom_fichier(char *dst, unsigned int max_len_dst, char *src,
                       char *buffer_erreur, int maxlen_erreur)
{
    /* la chaine dest doit être vide sinon ça signifie
       qu'on a passé deux fois la même option */
    if (strlen(dst)) {
        snprintf(buffer_erreur, maxlen_erreur,
                 "Vous avez passé deux fois la même option.\n"
                 "La deuxième fois vous avec passé :\n"
                 "<%s> en paramètre.\n", src);
        return -1;
    }
    if (strlen(src) >= max_len_dst) {
        snprintf(buffer_erreur, maxlen_erreur,
                 "Nom de fichier trop long.\n"
                 "il ne doit pas dépasser %u caractères\n",
                 max_len_dst - 1);
        return -1;
    }
    return 0;
}

int valide_ulong(char *param, unsigned long *retour,
                 char *buffer_erreur, int maxlen_erreur)
{
    char *ptr;

    *retour = strtoul(param, &ptr, 10);
    if ((param[0] != 0) && (ptr[0] == 0)) {
        return 0;
    }
    snprintf(buffer_erreur, maxlen_erreur,
             "Paramètre en entrée <%s> invalide.\n"
             "Il faut un nombre entier positif.\n", param);
    return -1;
}

int valide_opts(int argc, char *argv[], unsigned char *help,
                unsigned char *quiet_mode,
                char *nom_fichier_entree,
                int maxlen_nom_fichier_entree,
                char *nom_fichier_sortie,
                int maxlen_nom_fichier_sortie,
                char *buffer_erreur, int maxlen_erreur)
{
    /* paramètres possibles : voir l'aide en haut de ce fichier
     */
    static struct option long_options[] = {
        {"in", 1, 0, 0},
        {"out", 1, 0, 0},
        {"help", 0, 0, 0},
        {"quiet", 0, 0, 0},
        {0, 0, 0, 0}
    };

    /* lecture des options : */
    int this_option_optind;
    int option_index;
    int i;

    while (1) {
        this_option_optind = optind ? optind : 1;
        option_index = 0;

        /* Si l'option est suivie par ':' c'est quelle demande un argument : */
        i = getopt_long(argc, argv, "i:o:hq", long_options, &option_index);
        if (i == -1)
            break;

        switch (i) {
        case 0:
            switch (option_index) {
            case 0:
                /* "in" */
                if (valide_nom_fichier
                    (nom_fichier_entree, maxlen_nom_fichier_entree,
                     optarg, buffer_erreur, maxlen_erreur)) {
                    STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
                    return -1;
                }
                strcpy(nom_fichier_entree, optarg);
                break;
            case 1:
                /* "out" */
                if (valide_nom_fichier
                    (nom_fichier_sortie, maxlen_nom_fichier_sortie,
                     optarg, buffer_erreur, maxlen_erreur)) {
                    STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
                    return -1;
                }
                strcpy(nom_fichier_sortie, optarg);
                break;
            case 2:
                /* "help" */
                *help = 1;
                return 0;
                break;
            case 3:
                /* "quiet" */
                *quiet_mode = 1;
                break;
            default:
                snprintf(buffer_erreur, maxlen_erreur,
                         "?? option non gérée, c'est anormal.\n");
                STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
                return -1;

            }
            break;
        case 'i':
            if (valide_nom_fichier
                (nom_fichier_entree, maxlen_nom_fichier_entree,
                 optarg, buffer_erreur, maxlen_erreur)) {
                STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
                return -1;
            }
            strcpy(nom_fichier_entree, optarg);
            break;
        case 'o':
            if (valide_nom_fichier
                (nom_fichier_sortie, maxlen_nom_fichier_sortie,
                 optarg, buffer_erreur, maxlen_erreur)) {
                STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
                return -1;
            }
            strcpy(nom_fichier_sortie, optarg);
            break;
        case 'h':
            /* "help" */
            *help = 1;
            return 0;
            break;
        case 'q':
            /* "quiet" */
            *quiet_mode = 1;
            break;
        }
    }

    if (optind < argc) {
        printf("Options ignorées :");
        while (optind < argc)
            printf("%s ", argv[optind++]);
        printf("\n");
    }
    if (strlen(nom_fichier_entree) == 0) {
        snprintf(buffer_erreur, maxlen_erreur,
                 "Vous n'avez passé aucun fichier en entrée.\n");
        STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
        return -1;
    }
    if (strlen(nom_fichier_sortie) == 0) {
        snprintf(buffer_erreur, maxlen_erreur,
                 "Vous n'avez passé aucun fichier en sortie.\n");
        STRCAT_STR_USAGE(buffer_erreur, maxlen_erreur);
        return -1;
    }
    return 0;
}
