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

typedef StringBuffer<250> String;

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

static void testPointIsInside(Test& test) {
    Size size(200, 100);
    Frustum f(60.0f, 0.1f, 1000.0f, size);
    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));
    
    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) {
    Size size(200, 100);
    Frustum f(60.0f, 0.1f, 1000.0f, size);
    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));
    
    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();
}