#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <time.h>
#include <locale.h>
#include <monetary.h>
#include <math.h>
#include <complex.h>

int rand_n(int n)
{
    int partSize = 1 + (n == RAND_MAX ? 0 : (RAND_MAX - n) / (n + 1));
    int maxUsefull = partSize * n + (partSize - 1);
    int draw;

    do {
        draw = rand();
    } while (draw > maxUsefull);

    return draw / partSize;
}

void snprintf_format_monetaire(char *dest, int maxlen_dest,
                               unsigned long along)
{
    char buffer_tmp[6];
    double dtmp, divtmp;
    unsigned long ul_tmp;

    dest[0] = 0;
    divtmp = 0;
    dtmp = along;
    while ((dtmp / pow(10, divtmp)) >= 1) {
        divtmp += 3;
    }
    divtmp -= 3;
    while (divtmp >= 0) {
        ul_tmp = ((unsigned long) dtmp / (unsigned long) pow(10, divtmp));
        if (ul_tmp < 1000) {
            snprintf(buffer_tmp, sizeof(buffer_tmp - 1), "%lu",
                     (unsigned long) (ul_tmp % 1000));
        } else {
            snprintf(buffer_tmp, sizeof(buffer_tmp - 1), " %03lu",
                     (unsigned long) (ul_tmp % 1000));
        }
        strncat(dest, buffer_tmp, maxlen_dest);
        divtmp -= 3;
    }
    if (strlen(dest) == 0) {
        snprintf(dest, maxlen_dest, "%d", (int) 0);
    }
}

void print_format_monetaire(unsigned long along)
{
    char buffer_tmp[500];
    snprintf_format_monetaire(buffer_tmp, sizeof(buffer_tmp) - 1, along);
    printf(buffer_tmp);
}

/* pour éviter le warning, je ne sais pas comment faire autrement :
*/
extern struct tm *localtime_r(time_t *, struct tm *);

void fprintf_time_desc(FILE * stream, char *desc)
{
    time_t mytime;
    struct tm mytm;
    time(&mytime);
    localtime_r(&mytime, &mytm);

    fprintf(stream,
            "%s le %d/%d/%d à %02d:%02d:%02d\n",
            desc,
            mytm.tm_mday, mytm.tm_mon + 1, mytm.tm_year + 1900,
            mytm.tm_hour, mytm.tm_min, mytm.tm_sec);
}

void sprintf_time_desc(char *dest, int maxlen_dest, char *desc)
{
    time_t mytime;
    struct tm mytm;
    time(&mytime);
    localtime_r(&mytime, &mytm);
    snprintf(dest, maxlen_dest,
             "%s le %d/%d/%d à %02d:%02d:%02d\n",
             desc,
             mytm.tm_mday, mytm.tm_mon + 1, mytm.tm_year + 1900,
             mytm.tm_hour, mytm.tm_min, mytm.tm_sec);
}

void printf_time_desc(char *desc)
{
    fprintf_time_desc(stdout, desc);
}

void printf_time_debut_programme()
{
    printf_time_desc("-   Démarrage ");
}

void printf_time_fin_programme()
{
    printf_time_desc("    Fin du programme ");
}

/* fonction qui prend en paramètre un pointeur sur
   une chaine du type 'aa,bb,cc,dd,ee,...',
   qui récupère la première valeur (aa) et déplace
   le pointeur de chaine sur la suivante (bb)
   NB : pour mettre en place le filtre,
   j'aurais pu utiliser les outils d'expressions
   régulières (regcomp, regexec etc.) mais juste
   pour décoder quelque chose du type :
   'aa,' (x fois), autant le faire "à la main"
   (!) le paramètre **param doit être valide
       *et* il est modifié pour aller sur le
       début du 'aa,' suivant
*/
int recup_ul(char **pparam, unsigned long *pval)
{
    char *curr = *pparam;
    /* sauter les espaces */
    while (*curr) {
        if (*curr != ' ') {
            break;
        }
        curr++;
    }
    while (*curr) {
        if (*curr == ',') {
            if (curr != *pparam) {
                sscanf(*pparam, "%lu,", pval);
                *pparam = (++curr);
                return 0;
            }
        } else if ((*curr < '0') || (*curr > '9')) {
            return -1;
        }
        curr++;
    }
    /* si arrivé ici = fin = pas trouvé de ','
       => pas normal */
    return -1;
}
