#include "tests/FrustumTests.h"
#include "math/Frustum.h"
#include "tests/Test.h"
#include "utils/StringBuffer.h"

typedef StringBuffer<250> String;

static void testToString(Test& test) {
    Frustum f(60.0f, 0.1f, 1000.0f);
    test.checkEqual(String("("
                           "fieldOfView = 60.00, "
                           "nearClip = 0.10, "
                           "farClip = 1000.00)"),
                    String(f), "to string");
}

static void testPointIsInside(Test& test) {
    IntVector2 size(200, 100);
    Frustum f(60.0f, 0.1f, 1000.0f);
    f.updatePlanes(Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f),
                   Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 1.0f), size);

    test.checkEqual(true, f.isInside(Vector3(0.0f, 0.0f, 5.0f)),
                    "point is inside 1");
    test.checkEqual(false, f.isInside(Vector3(0.0f, 0.0f, 1004.0f)),
                    "point is inside 2");
    test.checkEqual(false, f.isInside(Vector3(0.0f, 0.0f, -5.0f)),
                    "point is inside 3");
    test.checkEqual(false, f.isInside(Vector3(0.0f, 50.0f, 5.0f)),
                    "point is inside 4");
    test.checkEqual(false, f.isInside(Vector3(0.0f, -50.0f, 5.0f)),
                    "point is inside 5");
    test.checkEqual(false, f.isInside(Vector3(50.0f, 0.0f, 5.0f)),
                    "point is inside 6");
    test.checkEqual(false, f.isInside(Vector3(-50.0f, 0.0f, 5.0f)),
                    "point is inside 7");
}

static void testSphereIsInside(Test& test) {
    IntVector2 size(200, 100);
    Frustum f(60.0f, 0.1f, 1000.0f);
    f.updatePlanes(Vector3(0.0f, 0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f),
                   Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 1.0f), size);

    test.checkEqual(true, f.isInside(Vector3(0.0f, 0.0f, 5.0f), 3.0f),
                    "sphere is inside 1");
    test.checkEqual(false, f.isInside(Vector3(0.0f, 0.0f, 1004.0f), 3.0f),
                    "sphere is inside 2");
    test.checkEqual(false, f.isInside(Vector3(0.0f, 0.0f, -5.0f), 3.0f),
                    "sphere is inside 3");
    test.checkEqual(false, f.isInside(Vector3(0.0f, 50.0f, 5.0f), 3.0f),
                    "sphere is inside 4");
    test.checkEqual(false, f.isInside(Vector3(0.0f, -50.0f, 5.0f), 3.0f),
                    "sphere is inside 5");
    test.checkEqual(false, f.isInside(Vector3(50.0f, 0.0f, 5.0f), 3.0f),
                    "sphere is inside 6");
    test.checkEqual(false, f.isInside(Vector3(-50.0f, 0.0f, 5.0f), 3.0f),
                    "sphere is inside 7");

    test.checkEqual(true, f.isInside(Vector3(0.0f, 0.0f, 5.0f), 3.0f),
                    "sphere is inside 8");
    test.checkEqual(true, f.isInside(Vector3(0.0f, 0.0f, 1004.0f), 50.0f),
                    "sphere is inside 9");
    test.checkEqual(true, f.isInside(Vector3(0.0f, 0.0f, -5.0f), 50.0f),
                    "sphere is inside 10");
    test.checkEqual(true, f.isInside(Vector3(0.0f, 50.0f, 5.0f), 50.0f),
                    "sphere is inside 11");
    test.checkEqual(true, f.isInside(Vector3(0.0f, -50.0f, 5.0f), 50.0f),
                    "sphere is inside 12");
    test.checkEqual(true, f.isInside(Vector3(50.0f, 0.0f, 5.0f), 50.0f),
                    "sphere is inside 13");
    test.checkEqual(true, f.isInside(Vector3(-50.0f, 0.0f, 5.0f), 50.0f),
                    "sphere is inside 14");
}

void FrustumTests::test() {
    Test test("Frustum");
    testToString(test);
    testPointIsInside(test);
    testSphereIsInside(test);
    test.finalize();
}