#include "../Tests.hpp"
#include "core/math/MatrixStack.hpp"

template class Core::MatrixStack<5>;
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;
    stack.push();
    stack.peek().scale(2.0f);
    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(bool light) {
    Matrices stack;
    for(int i = 0; i < 4; i++) {
        stack.push();
    }
    int limit = light ? 10000 : 1000000;
    for(int i = 0; i < limit; i++) {
        stack.push();
    }
}

static void testClear() {
    Matrices stack;
    stack.peek().scale(2.0f);
    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);
    stack.push();
    stack.peek().scale(3.0f);
    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);
    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);
}

static void testConstPeek() {
    const 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.peek());
}

void Core::testMatrixStack(bool light) {
    testInit();
    testPop();
    testPush(light);
    testClear();
    testToString1();
    testToString2();
    testToString3();
    testConstPeek();
}