/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#pragma once
#include "../libs.h"
#include "array.h"
#include "math.h"

/** Custom Array Definition */
typedef struct {
  /** The data storage */
  void *data;

  /** Size of each element within the array */
  size_t size;
  
  /** The count of elements currently in the array */
  int32_t length;

  /** Total count of elements the array can hold */
  int32_t total;
} dynarray_t;

/**
 * Create a dynamic array. Dynamic arrays are a more highlevel array style that
 * can offer great flexibility and ease-of-use, at the cost of memory, memory
 * fragmentation and some slight performance. Great for when you need something
 * like a traditional array, without the hassle of a linked list.
 * 
 * @param array Array to initialize.
 * @param size Size of each element within the array.
 * @param total Total number of elements that the array can hold.
 */
void dynArrayInit(dynarray_t *array, size_t size, int32_t total);

/**
 * Returns the pointer to an index within the array.
 * 
 * @param array Array to get from.
 * @param i Index to get
 * @return Pointer to that element.
 */
void * dynArrayGet(dynarray_t *array, int32_t i);

/**
 * Set something into the array.
 * 
 * @param array Array to set into.
 * @param i Index to set into.
 * @param data Pointer to the data to set.
 */
void dynArraySet(dynarray_t *array, int32_t i, void *data);

/**
 * Push an element into the array.
 * 
 * @param array Array to push in to.
 * @param data Pointer to the data to push.
 * @return The index that the data was pushed in to.
 */
int32_t dynArrayPush(dynarray_t *array, void *data);

/**
 * Create a new element in the array for you to use.
 * 
 * @param array Array to add to.
 * @return The index that the item was added to.
 */
int32_t dynArrayAdd(dynarray_t *array);

/**
 * "Pops" (Removes) the last element from the array.
 * 
 * @param array Array to pop.
 */
void dynArrayPop(dynarray_t *array);

/**
 * Removes elements from out of the array, and shuffles the remaining items.
 * This is useful for removing a specific item from an array and keeping the
 * holes out of the array. This will readjust the indexes of all elements that
 * appear after the spliced index.
 * 
 * @param array Array to splice.
 * @param start First index to splice.
 * @param count Count of elements to splice
 */
void dynArraySplice(dynarray_t *array, int32_t start, int32_t count);

/**
 * Dispose a previously created dynamic array.
 * 
 * @param array Dynamic array to dispose.
 */
void dynArrayDispose(dynarray_t *array);