#include "test_i32_array.h"
#include "wapp.h"

TestFuncResult test_i32_array(void) {
  b8 result;

  I32Array array = wapp_i32_array(1, 2, 3, 4, 5, 6, 7);
  result = array.count == 7 && array.capacity == 16;

  i32 *item;
  u64 count    = array.count;
  u64 index    = 0;
  b8 running  = true;
  while (running) {
      item   = wapp_i32_array_get(&array, index);
      result = result && item && (*item == (i32)(index + 1));

      ++index;
      running = index < count;
  }

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_with_capacity(void) {
  b8 result;

  I32Array array = wapp_i32_array_with_capacity(64);
  result = array.count == 0 && array.capacity == 64;

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_get(void) {
  b8 result = true;

  I32Array array = wapp_i32_array(0, 1, 2, 3, 4, 5, 6, 7, 8);

  i32 *item;
  u64 count    = array.count;
  u64 index    = 0;
  b8 running  = true;
  while (running) {
    item   = wapp_i32_array_get(&array, index);
    result = result && item && (*item == (i32)index);

    ++index;
    running = index < count;
  }

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_set(void) {
  b8 result = true;

  I32Array array = wapp_i32_array(0, 1, 2, 3, 4, 5, 6, 7, 8);

  i32 *item;
  u64 count    = array.count;
  u64 index    = 0;
  b8 running  = true;
  while (running) {
    i32 num = (i32)(index * 2);
    wapp_i32_array_set(&array, index, &num);
    item   = wapp_i32_array_get(&array, index);
    result = result && item && (*item == (i32)(index * 2));

    ++index;
    running = index < count;
  }

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_append_capped(void) {
  b8 result;

  I32Array array = wapp_i32_array_with_capacity(64);
  i32 item1 = 10;
  wapp_i32_array_append_capped(&array, &item1);

  result = array.count == 1;
  i32 *item = wapp_i32_array_get(&array, 0);
  result = result && item && *item == 10;

  array = wapp_i32_array(1);
  i32 item2 = 10;
  wapp_i32_array_append_capped(&array, &item2);

  result = result && array.count == 2;

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_extend_capped(void) {
  b8 result;

  I32Array array1 = wapp_i32_array(1, 2, 3, 4);
  I32Array array2 = wapp_i32_array(10, 20);

  result = array1.count == 4 && array2.count == 2;

  wapp_i32_array_extend_capped(&array1, &array2);

  result = result && array1.count == 6;

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_clear(void) {
  b8 result;

  I32Array array = wapp_i32_array(0, 1, 2, 3, 4, 5, 6, 7, 8);
  result = array.count == 9;

  wapp_i32_array_clear(&array);

  result = result && array.count == 0;

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_pop(void) {
  b8 result;

  I32Array array1 = wapp_i32_array(0, 1, 2, 3, 4, 5, 6, 7, 8);
  I32Array array2 = wapp_i32_array_with_capacity(32);

  i32 item1 = wapp_i32_array_pop(&array1);
  i32 item2 = wapp_i32_array_pop(&array2);

  result = item1 == 8 && item2 == 0;

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_copy_capped(void) {
  b8 result;

  I32Array src  = wapp_i32_array(1, 2, 3, 4, 5);
  I32Array dst1 = wapp_i32_array(1, 2, 3, 4, 5, 6);
  I32Array dst2 = wapp_i32_array(1, 2);

  u64 expected_count = 5;
  wapp_i32_array_copy_capped(&src, &dst1);
  result = dst1.count == expected_count;

  u64 index    = 0;
  b8 running  = true;
  while (running) {
    result = result && (*wapp_i32_array_get(&src, index) == *wapp_i32_array_get(&dst1, index));

    ++index;
    running = index < expected_count;
  }

  expected_count = 4;
  wapp_i32_array_copy_capped(&src, &dst2);
  result = result && dst2.count == expected_count;

  index   = 0;
  running = true;
  while (running) {
    result = result && (*wapp_i32_array_get(&src, index) == *wapp_i32_array_get(&dst2, index));

    ++index;
    running = index < expected_count;
  }

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_alloc_capacity(void) {
  b8 result;

  Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
  u64 capacity        = 32;
  I32Array *array     = wapp_i32_array_alloc_capacity(&allocator, capacity);

  result = array && array->capacity == capacity;

  wapp_mem_arena_allocator_destroy(&allocator);

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_append_alloc(void) {
  b8 result;

  Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
  I32Array array1     = wapp_i32_array(1, 2, 3, 4, 5, 6, 7, 8);
  I32Array array2     = wapp_i32_array(1, 2);

  i32 num = 10;
  I32Array *arr_ptr = wapp_i32_array_append_alloc(&allocator, &array1, &num);
  result = arr_ptr == &array1;

  u64 count    = 4;
  u64 index    = 0;
  b8 running  = true;
  while (running) {
    i32 num = (i32)index;
    arr_ptr = wapp_i32_array_append_alloc(&allocator, &array2, &num);

    ++index;
    running = index < count;
  }
  result = result && arr_ptr != &array2;

  wapp_mem_arena_allocator_destroy(&allocator);

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_extend_alloc(void) {
  b8 result;

  Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
  I32Array array1     = wapp_i32_array(1, 2, 3, 4, 5, 6, 7, 8);
  I32Array array2     = wapp_i32_array(1, 2);
  I32Array array3     = wapp_i32_array(1, 2, 3, 4);

  I32Array *arr_ptr = wapp_i32_array_extend_alloc(&allocator, &array1, &array3);
  result = arr_ptr == &array1;

  arr_ptr = wapp_i32_array_extend_alloc(&allocator, &array2, &array3);
  result  = result && arr_ptr != &array2;

  wapp_mem_arena_allocator_destroy(&allocator);

  return wapp_tester_result(result);
}

TestFuncResult test_i32_array_copy_alloc(void) {
  b8 result;

  Allocator allocator = wapp_mem_arena_allocator_init(MB(4));
  I32Array src        = wapp_i32_array(1, 2, 3, 4, 5);
  I32Array dst1       = wapp_i32_array(1, 2, 3, 4, 5, 6);
  I32Array dst2       = wapp_i32_array(1, 2);
  I32Array *array_ptr = nullptr;

  u64 expected_count = 5;
  array_ptr = wapp_i32_array_copy_alloc(&allocator, &src, &dst1);
  result = array_ptr->count == expected_count && array_ptr == &dst1;

  u64 index    = 0;
  b8 running  = true;
  while (running) {
    result = result && (*wapp_i32_array_get(&src, index) == *wapp_i32_array_get(array_ptr, index));

    ++index;
    running = index < expected_count;
  }

  expected_count = 5;
  array_ptr = wapp_i32_array_copy_alloc(&allocator, &src, &dst2);
  result = result && array_ptr->count == expected_count && array_ptr != &dst2;

  index   = 0;
  running = true;
  while (running) {
    result = result && (*wapp_i32_array_get(&src, index) == *wapp_i32_array_get(array_ptr, index));

    ++index;
    running = index < expected_count;
  }

  wapp_mem_arena_allocator_destroy(&allocator);

  return wapp_tester_result(result);
}
