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

#include "list.h"


List *list_new() {

    List *list = calloc(1, sizeof(List));
    return list;

}

void list_delete(List *list) {

    if (list->elements) {
        free(list->elements);
    }

    free(list);

}

void list_init(List *list) {

    memset(list, 0, sizeof(List));

}

void list_clear(List *list) {

    if (list->elements) {
        free(list->elements);
    }

    list_init(list);

}

void list_grow(List *list, size_t n) {

    if (n == 0) {
        n = LIST_DEFAULT_CAPACITY;
    }

    if (n > list->capacity) {
        list->elements = realloc(list->elements, n * sizeof(void*));
        list->capacity = n;
    }

}

void list_add(List *list, void *element) {

    if (list->size == list->capacity) {
        list_grow(list, list->capacity << 1);
    }

    list->elements[list->size++] = element;

}

int list_add_unique(List *list, void *element) {

    if (list_contains(list, element)) {
        return 0;
    }

    list_add(list, element);
    return 1;

}

int list_remove(List *list, void *element) {

    void **end = list->elements + list->size;

    for (void **l = list->elements; l < end; l++) {

        if (*l != element) {
            continue;
        }

        // Shift subsequent elements to the left
        for (; l < end - 1; l++) {
            *l = *(l+1);
        }

        list->size--;
        return 1;

    }

    return 0;

}

void list_remove_at(List *list, size_t index) {

    if (index >= list->size) {
        return;
    }

    void **l = list->elements + index;
    void **end = list->elements + list->size;

    // Shift subsequent elements to the left
    for (; l < end - 1; l++) {
        *l = *(l+1);
    }

    list->size--;

}

int list_contains(List *list, void *element) {

    LIST_FOR(list) {
        void *e = LIST_CUR(void);
        if (e == element) {
            return 1;
        }
    }

    return 0;

}