#include "Base/Type/Span.h"

#include "Tests/GTestWrapper/google_test.h"
#include <stdexcept>

constexpr double inf = std::numeric_limits<double>::infinity();

TEST(Span, Constructor)
{
    EXPECT_NO_THROW(Span limits5(-inf, -5.0));
    EXPECT_NO_THROW(Span limits6(-5.0, -4.0));
    EXPECT_NO_THROW(Span limits7(-4.0, inf));
    EXPECT_FAILED_ASSERT(Span limits8(-4, -5));
}

void check_eq(const Span& a, const Span& b)
{
    EXPECT_EQ(a.low(), b.low());
    EXPECT_EQ(a.hig(), b.hig());
}

TEST(Span, unite)
{
    Span limitless(-inf, inf);
    Span poslimit1(0, inf);
    Span poslimit2(4, inf);
    Span neglimit1(-inf, -1);
    Span neglimit2(-inf, 5);
    Span finite1(-3.0, 5.0);
    Span finite2(-1.0, 6.0);
    Span finite3(7.0, 15.0);
    Span limits(-inf, inf);

    limits = Span::unite(limitless, limitless);
    check_eq(limitless, limits);

    limits = Span::unite(limitless, poslimit1);
    check_eq(limitless, limits);
    limits = Span::unite(poslimit1, limitless);
    check_eq(limitless, limits);

    limits = Span::unite(limitless, neglimit1);
    check_eq(limitless, limits);
    limits = Span::unite(neglimit1, limitless);
    check_eq(limitless, limits);

    limits = Span::unite(limitless, finite1);
    check_eq(limitless, limits);
    limits = Span::unite(finite1, limitless);
    check_eq(limitless, limits);

    limits = Span::unite(poslimit1, poslimit2);
    check_eq(poslimit1, limits);
    limits = Span::unite(poslimit2, poslimit1);
    check_eq(poslimit1, limits);

    limits = Span::unite(poslimit1, neglimit1);
    check_eq(limitless, limits);
    limits = Span::unite(neglimit1, poslimit1);
    check_eq(limitless, limits);

    limits = Span::unite(neglimit1, neglimit2);
    check_eq(neglimit2, limits);
    limits = Span::unite(neglimit2, neglimit1);
    check_eq(neglimit2, limits);

    limits = Span::unite(finite1, finite2);
    check_eq(Span(-3, 6), limits);
    limits = Span::unite(finite2, finite1);
    check_eq(Span(-3, 6), limits);

    limits = Span::unite(finite1, finite3);
    check_eq(Span(-3, 15), limits);
    limits = Span::unite(finite3, finite1);
    check_eq(Span(-3, 15), limits);
}
