#include "../Tests.h"
#include "core/Components.h"

LIST(int, Int)
LIST_SOURCE(int, Int)
COMPONENTS(int, Int)
COMPONENTS_SOURCE(int, Int)

static void testAddForEach() {
    ComponentsInt c;
    initComponentsInt(&c);

    int* i1 = getOrAddComponentInt(&c, 1);
    if(TEST_NOT_NULL(i1)) {
        *i1 = 10;
    }
    int* i2 = getOrAddComponentInt(&c, 1);
    if(TEST_NOT_NULL(i2)) {
        *i2 = 15;
    }
    int* i3 = getOrAddComponentInt(&c, 5);
    if(TEST_NOT_NULL(i3)) {
        *i3 = 20;
    }
    int* i4 = getOrAddComponentInt(&c, 10);
    if(TEST_NOT_NULL(i4)) {
        *i4 = 30;
    }
    TEST_TRUE(i1 == i2);

    ComponentIteratorInt iter;
    initComponentIteratorInt(&iter, &c);
    if(TEST_TRUE(hasNextComponentNodeInt(&iter))) {
        ComponentNodeInt* n = nextComponentNodeInt(&iter);
        TEST_SIZE(1, n->entity);
        TEST_INT(15, *n->component);
    }
    if(TEST_TRUE(hasNextComponentNodeInt(&iter))) {
        ComponentNodeInt* n = nextComponentNodeInt(&iter);
        TEST_SIZE(5, n->entity);
        TEST_INT(20, *n->component);
    }
    if(TEST_TRUE(hasNextComponentNodeInt(&iter))) {
        ComponentNodeInt* n = nextComponentNodeInt(&iter);
        TEST_SIZE(10, n->entity);
        TEST_INT(30, *n->component);
    }
    TEST_FALSE(hasNextComponentNodeInt(&iter));
    destroyComponentsInt(&c);
}

static void testAddComponentForEach() {
    ComponentsInt c;
    initComponentsInt(&c);
    int* i1 = getOrAddComponentInt(&c, 1);
    if(TEST_NOT_NULL(i1)) {
        *i1 = 10;
    }
    int* i2 = getOrAddComponentInt(&c, 5);
    if(TEST_NOT_NULL(i2)) {
        *i2 = 20;
    }
    int* i3 = getOrAddComponentInt(&c, 10);
    if(TEST_NOT_NULL(i3)) {
        *i3 = 30;
    }

    int* iter = getComponentsStartInt(&c);
    int* end = getComponentsEndInt(&c);
    if(TEST_TRUE(iter != end)) {
        TEST_INT(10, *(iter++));
    }
    if(TEST_TRUE(iter != end)) {
        TEST_INT(20, *(iter++));
    }
    if(TEST_TRUE(iter != end)) {
        TEST_INT(30, *(iter++));
    }
    TEST_TRUE(iter == end);
    destroyComponentsInt(&c);
}

static void testRemove() {
    ComponentsInt c;
    initComponentsInt(&c);
    *getOrAddComponentInt(&c, 1) = 10;
    *getOrAddComponentInt(&c, 5) = 20;
    *getOrAddComponentInt(&c, 10) = 30;

    TEST_FALSE(removeComponentInt(&c, 20));
    TEST_TRUE(removeComponentInt(&c, 5));
    TEST_FALSE(removeComponentInt(&c, 30));

    *getOrAddComponentInt(&c, 20) = 40;
    TEST_TRUE(removeComponentInt(&c, 20));

    int* i1 = searchComponentInt(&c, 1);
    int* i3 = searchComponentInt(&c, 10);
    TEST_NULL(searchComponentInt(&c, 5));
    if(TEST_NOT_NULL(i1) && TEST_NOT_NULL(i3)) {
        TEST_INT(10, *i1);
        TEST_INT(30, *i3);
    }

    TEST_TRUE(removeComponentInt(&c, 10));
    i1 = searchComponentInt(&c, 1);
    TEST_NULL(searchComponentInt(&c, 5));
    TEST_NULL(searchComponentInt(&c, 10));
    if(TEST_NOT_NULL(i1)) {
        TEST_INT(10, *i1);
    }

    TEST_TRUE(removeComponentInt(&c, 1));
    TEST_NULL(searchComponentInt(&c, 1));
    TEST_NULL(searchComponentInt(&c, 5));
    TEST_NULL(searchComponentInt(&c, 10));

    destroyComponentsInt(&c);
}

void testComponents() {
    testAddForEach();
    testAddComponentForEach();
    testRemove();
}