#include "crepe_stream.h"
#include <stdio.h>
#include "toolbox.h"
//#############################
// FCT AUX
// ############################

typedef int (*comparator)(void *, void *);

char *topping(enum topping topping){
// C'est mooooche :/ /FIXME A refaire

    if(topping == NOTHING) return"nothing";
    else if(topping == SUGAR) return"sugar";
    else if (topping == CHOCOLATE) return"chocolate";
    else if (topping == WHIPPED_CREAM) return"whipped cream";
    else if (topping == CHEESE) return"cheese";
    else if (topping == MEAT) return"meat";
    else if(topping == EGG) return"egg";
    else return "WTF Rien ?? un topping de None ?";
    
}

char *dough(enum dough dough){
// c'est mooooche, j'iame pas raah //FIXME

    if (dough == WHEAT) return "wheat";
    else if (dough == BUCKWHEAT) return "buckwheat";
    else return "WTF encore rien...";
}

void print_arr(struct crepe *crepe){
    
    printf("%s: $%i\n", crepe->name, crepe->price);
    printf("- Made out of %s\n", dough(crepe->dough));
    printf("- Contains %s with %s on top\n", topping(crepe->inside), topping(crepe->outside));
}

int lower(struct crepe *a, struct crepe *b){

    if (a->price % 2 == 0 && b->price % 2 != 0) return -1;
    else if (a->price % 2 != 0 && b->price % 2 == 0) return 1;
    else if (a->price % 2 == 0 && b->price % 2 ==0) return a->price - b->price;
    else return b->price - a->price;
}

void name(void *a, void *b){

    struct crepe *c = b;
    char **rslt = a;
    *rslt = c->name;
}

int contain_meat(void *ptr){

    struct crepe *crepe = ptr;

    if(crepe->inside == MEAT || crepe->outside == MEAT) return 0;
    return 1;

}

void *clc_price(void *acc, void *elem){
    
    int *tot = acc;
    struct crepe *c = elem;
    *tot += c->price;
    return tot;
}

//########################
//FCT TP
//########################
struct array *sort_by_prices(struct array *arr)
{
   arr = sort(arr, (comparator)lower);
   return arr;
}

struct array *names(struct array *arr)
{
    return map(arr, sizeof(char *), (mapper)name);
}

struct array *vegetarian(struct array *arr)
{
    return filter(arr, (predicate)contain_meat);
}

int total_price(struct array *arr)
{
    int total = 0;
    reduce(arr, &total, (reducer)clc_price);
    return total;
}

void print_menu(struct array *arr)
{
    foreach(arr, (acceptor)&print_arr);

}
/*
#include <stdlib.h>

int main(void)
{
    struct array arr = {
        .elem_size = sizeof(struct crepe),
        .len = 4,
        .data = calloc(4, sizeof(struct crepe)),
    };
    struct crepe *data = arr.data;
    data[0] = (struct crepe){
        .name = "Dairy",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = EGG,
        .price = 5,
    };
    data[1] = (struct crepe){
        .name = "Raclette",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = MEAT,
        .price = 8,
    };
    data[2] = (struct crepe){
        .name = "Choco",
        .dough = WHEAT,
        .inside = CHOCOLATE,
        .outside = WHIPPED_CREAM,
        .price = 6,
    };
    data[3] = (struct crepe){
        .name = "Sugary",
        .dough = WHEAT,
        .inside = SUGAR,
        .outside = NOTHING,
        .price = 7,
    };

    printf("%d\n", total_price(&arr));

    free(arr.data);
}
*/

/*
#include <stdlib.h>

int main(void)
{
    struct array arr = {
        .elem_size = sizeof(struct crepe),
        .len = 4,
        .data = calloc(4, sizeof(struct crepe)),
    };
    struct crepe *data = arr.data;
    data[0] = (struct crepe){
        .name = "Dairy",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = EGG,
        .price = 5,
    };
    data[1] = (struct crepe){
        .name = "Raclette",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = MEAT,
        .price = 8,
    };
    data[2] = (struct crepe){
        .name = "Choco",
        .dough = WHEAT,
        .inside = CHOCOLATE,
        .outside = WHIPPED_CREAM,
        .price = 6,
    };
    data[3] = (struct crepe){
        .name = "Sugary",
        .dough = WHEAT,
        .inside = SUGAR,
        .outside = NOTHING,
        .price = 7,
    };

    print_menu(vegetarian(&arr));

    free(arr.data);
}
*/

/*
#include <stdlib.h>

void print_string(char **str)
{
    puts(*str);
}

int main(void)
{
    struct array arr = {
        .elem_size = sizeof(struct crepe),
        .len = 4,
        .data = calloc(4, sizeof(struct crepe)),
    };
    struct crepe *data = arr.data;
    data[0] = (struct crepe){
        .name = "Dairy",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = EGG,
        .price = 5,
    };
    data[1] = (struct crepe){
        .name = "Raclette",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = MEAT,
        .price = 8,
    };
    data[2] = (struct crepe){
        .name = "Choco",
        .dough = WHEAT,
        .inside = CHOCOLATE,
        .outside = WHIPPED_CREAM,
        .price = 6,
    };
    data[3] = (struct crepe){
        .name = "Sugary",
        .dough = WHEAT,
        .inside = SUGAR,
        .outside = NOTHING,
        .price = 7,
    };

    foreach(names(&arr), (acceptor)&print_string);

    free(arr.data);
}
*/

/*
#include <stdlib.h>

int main(void)
{
    struct array arr = {
        .elem_size = sizeof(struct crepe),
        .len = 4,
        .data = calloc(4, sizeof(struct crepe)),
    };
    struct crepe *data = arr.data;
    data[0] = (struct crepe){
        .name = "Dairy",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = EGG,
        .price = 5,
    };
    data[1] = (struct crepe){
        .name = "Raclette",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = MEAT,
        .price = 8,
    };
    data[2] = (struct crepe){
        .name = "Choco",
        .dough = WHEAT,
        .inside = CHOCOLATE,
        .outside = WHIPPED_CREAM,
        .price = 6,
    };
    data[3] = (struct crepe){
        .name = "Sugary",
        .dough = WHEAT,
        .inside = SUGAR,
        .outside = NOTHING,
        .price = 7,
    };

    print_menu(sort_by_prices(&arr));

    free(arr.data);
}
*/
/*
#include <stdlib.h>

int main(void)
{
    struct array arr = {
        .elem_size = sizeof(struct crepe),
        .len = 4,
        .data = calloc(4, sizeof(struct crepe)),
    };
    struct crepe *data = arr.data;
    data[0] = (struct crepe){
        .name = "Dairy",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = EGG,
        .price = 5,
    };
    data[1] = (struct crepe){
        .name = "Raclette",
        .dough = BUCKWHEAT,
        .inside = CHEESE,
        .outside = MEAT,
        .price = 8,
    };
    data[2] = (struct crepe){
        .name = "Choco",
        .dough = WHEAT,
        .inside = CHOCOLATE,
        .outside = WHIPPED_CREAM,
        .price = 6,
    };
    data[3] = (struct crepe){
        .name = "Sugary",
        .dough = WHEAT,
        .inside = SUGAR,
        .outside = NOTHING,
        .price = 7,
    };

    print_menu(&arr);

    free(arr.data);
}
*/
