#include "vector.h"

// Initial capacity for a new vector
#define VECTOR_INITIAL_CAPACITY 4

// Create a new vector
vector* vector_create() {
    vector* v = (vector*)malloc(sizeof(vector));
    if (!v) return NULL; // Return NULL if allocation fails

    v->capacity = VECTOR_INITIAL_CAPACITY;
    v->size = 0;
    v->items = (void**)malloc(sizeof(void*) * v->capacity);
    if (!v->items) {
        free(v); // Free the vector if item allocation fails
        return NULL;
    }

    return v;
}

// Destroy the vector and free allocated memory
void vector_destroy(vector* v) {
    if (v) {
        free(v->items);
        free(v);
    }
}

// Push an item to the back of the vector
int vector_push_back(vector* v, void* item) {
    // Resize the vector if it's full
    if (v->size == v->capacity) {
        if (vector_resize(v, v->capacity * 2) != 0) {
            return -1; // Return -1 on failure to resize
        }
    }

    v->items[v->size++] = item; // Add the new item
    return 0; // Success
}

// Get the item at a specific index
void* vector_get(vector* v, size_t index) {
    if (index >= v->size) return NULL; // Return NULL if index is out of bounds
    return v->items[index];
}

// Set an item at a specific index
int vector_set(vector* v, size_t index, void* item) {
    if (index >= v->size) return -1; // Return -1 if index is out of bounds
    v->items[index] = item;
    return 0; // Success
}

// Get the size of the vector
size_t vector_size(vector* v) {
    return v->size;
}

// Resize the vector's internal array
int vector_resize(vector* v, size_t new_capacity) {
    // Allocate new memory for the resized array
    void** new_items = (void**)malloc(sizeof(void*) * new_capacity);
    if (!new_items) return -1; // Return -1 on failure

    // Copy the old items into the new array
    for (size_t i = 0; i < v->size; i++) {
        new_items[i] = v->items[i];
    }

    // Free the old memory
    free(v->items);

    // Update the vector's internal state
    v->items = new_items;
    v->capacity = new_capacity;

    return 0; // Success
}
