#include "test_str8_list.h"
#include "wapp.h"

TestFuncResult test_str8_list_get(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");
  Str8 s4 = wapp_str8_lit("4");
  Str8 s5 = wapp_str8_lit("5");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);
  Str8Node n4   = wapp_str8_node_from_str8(s4);
  Str8Node n5   = wapp_str8_node_from_str8(s5);

  wapp_dbl_list_push_back(Str8, &list, &n1);
  wapp_dbl_list_push_back(Str8, &list, &n2);
  wapp_dbl_list_push_back(Str8, &list, &n3);
  wapp_dbl_list_push_back(Str8, &list, &n4);
  wapp_dbl_list_push_back(Str8, &list, &n5);

  Str8Node *node = wapp_dbl_list_get(Str8, Str8Node, &list, 0);
  result = node->item == &s1 && wapp_str8_equal(node->item, &s1);

  node = wapp_dbl_list_get(Str8, Str8Node, &list, 1);
  result = result && node->item == &s2 && wapp_str8_equal(node->item, &s2);

  node = wapp_dbl_list_get(Str8, Str8Node, &list, 2);
  result = result && node->item == &s3 && wapp_str8_equal(node->item, &s3);

  node = wapp_dbl_list_get(Str8, Str8Node, &list, 3);
  result = result && node->item == &s4 && wapp_str8_equal(node->item, &s4);

  node = wapp_dbl_list_get(Str8, Str8Node, &list, 4);
  result = result && node->item == &s5 && wapp_str8_equal(node->item, &s5);

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_push_front(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);

  wapp_dbl_list_push_front(Str8, &list, &n1);
  result = list.first == list.last && list.first == &n1 && list.first->item == &s1 && wapp_str8_list_total_size(&list) == 1 && list.node_count == 1;

  wapp_dbl_list_push_front(Str8, &list, &n2);
  result = result && list.first == &n2 && list.first->item == &s2 && wapp_str8_list_total_size(&list) == 2 && list.node_count == 2;

  wapp_dbl_list_push_front(Str8, &list, &n3);
  result = result && list.first == &n3 && list.first->item == &s3 && wapp_str8_list_total_size(&list) == 3 && list.node_count == 3;

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_push_back(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);

  wapp_dbl_list_push_back(Str8, &list, &n1);
  result = list.first == list.last && list.last == &n1 && list.last->item == &s1 && wapp_str8_list_total_size(&list) == 1 && list.node_count == 1;

  wapp_dbl_list_push_back(Str8, &list, &n2);
  result = result && list.last == &n2 && list.last->item == &s2 && wapp_str8_list_total_size(&list) == 2 && list.node_count == 2;

  wapp_dbl_list_push_back(Str8, &list, &n3);
  result = result && list.last == &n3 && list.last->item == &s3 && wapp_str8_list_total_size(&list) == 3 && list.node_count == 3;

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_insert(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");
  Str8 s4 = wapp_str8_lit("4");
  Str8 s5 = wapp_str8_lit("5");
  Str8 s6 = wapp_str8_lit("6");
  Str8 s7 = wapp_str8_lit("7");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);
  Str8Node n4   = wapp_str8_node_from_str8(s4);
  Str8Node n5   = wapp_str8_node_from_str8(s5);
  Str8Node n6   = wapp_str8_node_from_str8(s6);
  Str8Node n7   = wapp_str8_node_from_str8(s7);

  wapp_dbl_list_push_back(Str8, &list, &n1);
  wapp_dbl_list_push_back(Str8, &list, &n2);
  wapp_dbl_list_push_back(Str8, &list, &n3);
  wapp_dbl_list_push_back(Str8, &list, &n4);
  wapp_dbl_list_push_back(Str8, &list, &n5);

  Str8Node *node;
  wapp_dbl_list_insert(Str8, &list, &n6, 2);
  node   = wapp_dbl_list_get(Str8, Str8Node, &list, 2);
  result = node != NULL && node->item == &s6 && wapp_str8_list_total_size(&list) == 6 && list.node_count == 6;
  wapp_dbl_list_insert(Str8, &list, &n7, 5);
  node   = wapp_dbl_list_get(Str8, Str8Node, &list, 5);
  result = result && node != NULL && node->item == &s7 && wapp_str8_list_total_size(&list) == 7 && list.node_count == 7;

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_pop_front(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");
  Str8 s4 = wapp_str8_lit("4");
  Str8 s5 = wapp_str8_lit("5");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);
  Str8Node n4   = wapp_str8_node_from_str8(s4);
  Str8Node n5   = wapp_str8_node_from_str8(s5);

  wapp_dbl_list_push_back(Str8, &list, &n1);
  wapp_dbl_list_push_back(Str8, &list, &n2);
  wapp_dbl_list_push_back(Str8, &list, &n3);
  wapp_dbl_list_push_back(Str8, &list, &n4);
  wapp_dbl_list_push_back(Str8, &list, &n5);

  Str8Node *node = wapp_dbl_list_pop_front(Str8, Str8Node, &list);
  result = node == &n1 && node->item == &s1 && wapp_str8_equal(node->item, &s1) && wapp_str8_list_total_size(&list) == 4 && list.node_count == 4;

  node = wapp_dbl_list_pop_front(Str8, Str8Node, &list);
  result = result && node == &n2 && node->item == &s2 && wapp_str8_equal(node->item, &s2) && wapp_str8_list_total_size(&list) == 3 && list.node_count == 3;

  node = wapp_dbl_list_pop_front(Str8, Str8Node, &list);
  result = result && node == &n3 && node->item == &s3 && wapp_str8_equal(node->item, &s3) && wapp_str8_list_total_size(&list) == 2 && list.node_count == 2;

  node = wapp_dbl_list_pop_front(Str8, Str8Node, &list);
  result = result && node == &n4 && node->item == &s4 && wapp_str8_equal(node->item, &s4) && wapp_str8_list_total_size(&list) == 1 && list.node_count == 1;

  node = wapp_dbl_list_pop_front(Str8, Str8Node, &list);
  result = result && node == &n5 && node->item == &s5 && wapp_str8_equal(node->item, &s5) && wapp_str8_list_total_size(&list) == 0 && list.node_count == 0;

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_pop_back(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");
  Str8 s4 = wapp_str8_lit("4");
  Str8 s5 = wapp_str8_lit("5");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);
  Str8Node n4   = wapp_str8_node_from_str8(s4);
  Str8Node n5   = wapp_str8_node_from_str8(s5);

  wapp_dbl_list_push_front(Str8, &list, &n1);
  wapp_dbl_list_push_front(Str8, &list, &n2);
  wapp_dbl_list_push_front(Str8, &list, &n3);
  wapp_dbl_list_push_front(Str8, &list, &n4);
  wapp_dbl_list_push_front(Str8, &list, &n5);

  Str8Node *node = wapp_dbl_list_pop_back(Str8, Str8Node, &list);
  result = node == &n1 && node->item == &s1 && wapp_str8_equal(node->item, &s1) && wapp_str8_list_total_size(&list) == 4 && list.node_count == 4;

  node = wapp_dbl_list_pop_back(Str8, Str8Node, &list);
  result = result && node == &n2 && node->item == &s2 && wapp_str8_equal(node->item, &s2) && wapp_str8_list_total_size(&list) == 3 && list.node_count == 3;

  node = wapp_dbl_list_pop_back(Str8, Str8Node, &list);
  result = result && node == &n3 && node->item == &s3 && wapp_str8_equal(node->item, &s3) && wapp_str8_list_total_size(&list) == 2 && list.node_count == 2;

  node = wapp_dbl_list_pop_back(Str8, Str8Node, &list);
  result = result && node == &n4 && node->item == &s4 && wapp_str8_equal(node->item, &s4) && wapp_str8_list_total_size(&list) == 1 && list.node_count == 1;

  node = wapp_dbl_list_pop_back(Str8, Str8Node, &list);
  result = result && node == &n5 && node->item == &s5 && wapp_str8_equal(node->item, &s5) && wapp_str8_list_total_size(&list) == 0 && list.node_count == 0;

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_remove(void) {
  b8 result;

  Str8 s1 = wapp_str8_lit("1");
  Str8 s2 = wapp_str8_lit("2");
  Str8 s3 = wapp_str8_lit("3");
  Str8 s4 = wapp_str8_lit("4");
  Str8 s5 = wapp_str8_lit("5");

  Str8List list = wapp_dbl_list(Str8, Str8List);
  Str8Node n1   = wapp_str8_node_from_str8(s1);
  Str8Node n2   = wapp_str8_node_from_str8(s2);
  Str8Node n3   = wapp_str8_node_from_str8(s3);
  Str8Node n4   = wapp_str8_node_from_str8(s4);
  Str8Node n5   = wapp_str8_node_from_str8(s5);

  wapp_dbl_list_push_back(Str8, &list, &n1);
  wapp_dbl_list_push_back(Str8, &list, &n2);
  wapp_dbl_list_push_back(Str8, &list, &n3);
  wapp_dbl_list_push_back(Str8, &list, &n4);
  wapp_dbl_list_push_back(Str8, &list, &n5);

  Str8Node *node = wapp_dbl_list_remove(Str8, Str8Node, &list, 0);
  result = node == &n1 && node->item == &s1 && wapp_str8_equal(node->item, &s1) && wapp_str8_list_total_size(&list) == 4 && list.node_count == 4;

  node = wapp_dbl_list_remove(Str8, Str8Node, &list, 0);
  result = result && node == &n2 && node->item == &s2 && wapp_str8_equal(node->item, &s2) && wapp_str8_list_total_size(&list) == 3 && list.node_count == 3;

  node = wapp_dbl_list_remove(Str8, Str8Node, &list, 0);
  result = result && node == &n3 && node->item == &s3 && wapp_str8_equal(node->item, &s3) && wapp_str8_list_total_size(&list) == 2 && list.node_count == 2;

  node = wapp_dbl_list_remove(Str8, Str8Node, &list, 0);
  result = result && node == &n4 && node->item == &s4 && wapp_str8_equal(node->item, &s4) && wapp_str8_list_total_size(&list) == 1 && list.node_count == 1;

  node = wapp_dbl_list_remove(Str8, Str8Node, &list, 0);
  result = result && node == &n5 && node->item == &s5 && wapp_str8_equal(node->item, &s5) && wapp_str8_list_total_size(&list) == 0 && list.node_count == 0;

  return wapp_tester_result(result);
}

TestFuncResult test_str8_list_empty(void) {
  b8 result;

  Str8List list = wapp_dbl_list(Str8, Str8List);
  wapp_dbl_list_push_back(Str8, &list, &wapp_str8_node_from_cstr("Hello"));
  wapp_dbl_list_push_back(Str8, &list, &wapp_str8_node_from_cstr("from"));
  wapp_dbl_list_push_back(Str8, &list, &wapp_str8_node_from_cstr("wizapp"));
  wapp_dbl_list_push_back(Str8, &list, &wapp_str8_node_from_cstr("stdlib"));

  wapp_dbl_list_empty(Str8, &list);

  result = list.first == NULL && list.last == NULL && list.node_count == 0 && wapp_str8_list_total_size(&list) == 0;

  return wapp_tester_result(result);
}
