#include "tests/MatrixStackTests.h"

#include "math/MatrixStack.h"
#include "test/Test.h"

using Matrices = Core::MatrixStack<5>;

static void testInit() {
    Core::Matrix m;
    Matrices stack;
    for(int i = 0; i < 16; i++) {
        CORE_TEST_FLOAT(m.getValues()[i], stack.peek().getValues()[i], 0.0f);
    }
}

static void testPop() {
    Matrices stack;
    CORE_TEST_ERROR(stack.push());
    stack.peek().scale(2.0f);
    CORE_TEST_ERROR(stack.pop());
    Core::Matrix m;
    for(int i = 0; i < 16; i++) {
        CORE_TEST_FLOAT(m.getValues()[i], stack.peek().getValues()[i], 0.0f);
    }
}

static void testPush() {
    Matrices stack;
    for(int i = 0; i < 4; i++) {
        CORE_TEST_ERROR(stack.push());
    }
    for(int i = 0; i < 1000000; i++) {
        CORE_TEST_EQUAL(Core::Error::CAPACITY_REACHED, stack.push());
    }
}

static void testClear() {
    Matrices stack;
    stack.peek().scale(2.0f);
    CORE_TEST_ERROR(stack.push());
    stack.peek().scale(2.0f);
    stack.clear();
    Core::Matrix m;
    for(int i = 0; i < 16; i++) {
        CORE_TEST_FLOAT(m.getValues()[i], stack.peek().getValues()[i], 0.0f);
    }
}

static void testToString1() {
    Matrices stack;
    stack.peek().scale(2.0f);
    CORE_TEST_ERROR(stack.push());
    stack.peek().scale(3.0f);
    CORE_TEST_ERROR(stack.push());
    stack.peek().scale(4.0f);
    CORE_TEST_STRING("["
                     "[[2.00, 0.00, 0.00, 0.00], "
                     "[0.00, 2.00, 0.00, 0.00], "
                     "[0.00, 0.00, 2.00, 0.00], "
                     "[0.00, 0.00, 0.00, 1.00]], "
                     "[[6.00, 0.00, 0.00, 0.00], "
                     "[0.00, 6.00, 0.00, 0.00], "
                     "[0.00, 0.00, 6.00, 0.00], "
                     "[0.00, 0.00, 0.00, 1.00]], "
                     "[[24.00, 0.00, 0.00, 0.00], "
                     "[0.00, 24.00, 0.00, 0.00], "
                     "[0.00, 0.00, 24.00, 0.00], "
                     "[0.00, 0.00, 0.00, 1.00]]"
                     "]",
                     stack);
}

static void testToString2() {
    Matrices stack;
    stack.peek().scale(2.0f);
    CORE_TEST_ERROR(stack.push());
    stack.peek().scale(3.0f);
    CORE_TEST_STRING("["
                     "[[2.00, 0.00, 0.00, 0.00], "
                     "[0.00, 2.00, 0.00, 0.00], "
                     "[0.00, 0.00, 2.00, 0.00], "
                     "[0.00, 0.00, 0.00, 1.00]], "
                     "[[6.00, 0.00, 0.00, 0.00], "
                     "[0.00, 6.00, 0.00, 0.00], "
                     "[0.00, 0.00, 6.00, 0.00], "
                     "[0.00, 0.00, 0.00, 1.00]]"
                     "]",
                     stack);
}

static void testToString3() {
    Matrices stack;
    CORE_TEST_STRING("["
                     "[[1.00, 0.00, 0.00, 0.00], "
                     "[0.00, 1.00, 0.00, 0.00], "
                     "[0.00, 0.00, 1.00, 0.00], "
                     "[0.00, 0.00, 0.00, 1.00]]"
                     "]",
                     stack);
}

void Core::MatrixStackTests::test() {
    testInit();
    testPop();
    testPush();
    testClear();
    testToString1();
    testToString2();
    testToString3();
}