#include "tests/FrustumTests.h"

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

using V3 = Core::Vector3;

static void testToString() {
    Core::Frustum f(60.0f, 0.1f, 1000.0f);
    CORE_TEST_STRING("(tan = 0.58, nearClip = 0.10, farClip = 1000.00)", f);
}

static void testPointIsInside() {
    Core::IntVector2 size(200, 100);
    Core::Frustum f(60.0f, 0.1f, 1000.0f);
    f.updatePlanes(V3(0.0f, 0.0f, 0.0f), V3(1.0f, 0.0f, 0.0f),
                   V3(0.0f, 1.0f, 0.0f), V3(0.0f, 0.0f, 1.0f), size);

    CORE_TEST_TRUE(f.isInside(V3(0.0f, 0.0f, 5.0f)));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, 0.0f, 1004.0f)));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, 0.0f, -5.0f)));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, 50.0f, 5.0f)));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, -50.0f, 5.0f)));
    CORE_TEST_FALSE(f.isInside(V3(50.0f, 0.0f, 5.0f)));
    CORE_TEST_FALSE(f.isInside(V3(-50.0f, 0.0f, 5.0f)));
}

static void testSphereIsInside() {
    Core::IntVector2 size(200, 100);
    Core::Frustum f(60.0f, 0.1f, 1000.0f);
    f.updatePlanes(V3(0.0f, 0.0f, 0.0f), V3(1.0f, 0.0f, 0.0f),
                   V3(0.0f, 1.0f, 0.0f), V3(0.0f, 0.0f, 1.0f), size);

    CORE_TEST_TRUE(f.isInside(V3(0.0f, 0.0f, 5.0f), 3.0f));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, 0.0f, 1004.0f), 3.0f));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, 0.0f, -5.0f), 3.0f));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, 50.0f, 5.0f), 3.0f));
    CORE_TEST_FALSE(f.isInside(V3(0.0f, -50.0f, 5.0f), 3.0f));
    CORE_TEST_FALSE(f.isInside(V3(50.0f, 0.0f, 5.0f), 3.0f));
    CORE_TEST_FALSE(f.isInside(V3(-50.0f, 0.0f, 5.0f), 3.0f));

    CORE_TEST_TRUE(f.isInside(V3(0.0f, 0.0f, 5.0f), 3.0f));
    CORE_TEST_TRUE(f.isInside(V3(0.0f, 0.0f, 1004.0f), 50.0f));
    CORE_TEST_TRUE(f.isInside(V3(0.0f, 0.0f, -5.0f), 50.0f));
    CORE_TEST_TRUE(f.isInside(V3(0.0f, 50.0f, 5.0f), 50.0f));
    CORE_TEST_TRUE(f.isInside(V3(0.0f, -50.0f, 5.0f), 50.0f));
    CORE_TEST_TRUE(f.isInside(V3(50.0f, 0.0f, 5.0f), 50.0f));
    CORE_TEST_TRUE(f.isInside(V3(-50.0f, 0.0f, 5.0f), 50.0f));
}

void Core::FrustumTests::test() {
    testToString();
    testPointIsInside();
    testSphereIsInside();
}