#include "basics.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

struct list *list_append(struct list *l, int e)
{
    
    struct list *new_node = malloc(sizeof(struct list));
    if(!new_node) return NULL;

    new_node->data = e;
    new_node->next = l;

    return new_node;
/*
   struct list *tmp = l;
    
    struct list *new_node = calloc(1, sizeof(struct list));
    if (!new_node) return NULL;

    new_node->data = e;
    if(!l) return new_node;
    
    while (tmp->next != NULL) tmp = tmp->next;
    tmp->next = new_node;
    return l;
    */
}
size_t list_count(struct list *l){
    
    int nbr_nodes = 0;
    //if (!l) return nbr_nodes;
    
    struct list *tmp = l;
    
    //nbr_nodes ++;
    while(tmp != NULL) {
        nbr_nodes ++;
        tmp = tmp->next;
    }

    return nbr_nodes;
    
}

int list_insert(struct list **l, size_t index, int e){

    if(!l) return 1;
    
    struct list *new_node = malloc(sizeof(struct list));
    if(!new_node) return 1;

    if(index == 0){
        
        *l = list_append(*l, e);
        /*
        new_node->data = e;
        new_node->next = *l;
        *l = new_node;
        */
        return 0;
    }

    struct list *tmp = *l;
    size_t ind = 0;

    while(tmp != NULL && ind <index - 1){

        tmp = tmp->next;
        ind ++;
    }
    
    if (!tmp) return 1;

    new_node->data = e;
    new_node->next = tmp->next;
    tmp->next = new_node;

    return 0;

}

struct list *list_get(struct list *l, size_t index){

    struct list *tmp = l;
    size_t ind = 0;
    
    while(tmp != NULL && ind < index){
        tmp = tmp->next;
        ind ++;
    } 

    return tmp;

}

void list_destroy(struct list *l){

    if (!l) return;
    
    list_destroy(l->next);
    
    free(l);
}

struct list *list_find(struct list *l, int e){

    struct list *tmp = l;
    
    while (tmp != NULL && tmp->data != e) tmp = tmp->next;

    return tmp;

}

struct list *list_delete_at(struct list **l, size_t index){

    if (!l || !*l) return NULL;

    struct list *old = *l;

    if ( index == 0){
        *l = old->next;
        return old;
    }

    struct list *tmp = *l;

    size_t ind = 0;
    while(tmp != NULL && ind < index - 1){
        
        tmp = tmp->next;
        ind ++;
    }

    if (ind == index - 1) {
        old = tmp->next;
        tmp->next = old->next;
        return old;
    }

    return NULL;

}

int list_remove(struct list **l, int e){

    struct list *old = NULL;
    struct list *tmp = *l;

    while (tmp != NULL && tmp->data != e){
    
        old = tmp;
        tmp = tmp->next;
    }

    if (!tmp) return 0;

    if(!old) *l = tmp->next;
    else old->next = tmp->next;

    free(tmp);

    return 1;
}

void list_print(struct list *l){

    struct list *tmp = l;

    while (tmp != NULL){
        
        printf("%i",tmp->data);

        if (tmp->next != NULL) printf(" -> ");

        tmp = tmp->next;

    }

    printf("\n");
}
/*
int main(void)
{
    struct list *l = NULL;

    l = list_append(l, 3);
    l = list_append(l, 2);
    l = list_append(l, 1);

    // l = [1] -> [2] -> [3]
    list_insert(&l, 1, 99);  // l = [1] -> [99] -> [2] -> [3], and list_insert returns 0
    list_insert(&l, 9, 99);  // list unchanged, returns 1
    
    list_print(l);

    list_destroy(l);

    return 0;
}
*/
