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

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

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

TEST(ZLimitsTest, ZLimitsIsFinite)
{
    ZLimits limitless;
    ZLimits poslimit(0, inf);
    ZLimits neglimit(-inf, 0);
    ZLimits finite(-3.0, 5.0);
    EXPECT_FALSE(limitless.isFinite());
    EXPECT_FALSE(poslimit.isFinite());
    EXPECT_FALSE(neglimit.isFinite());
    EXPECT_TRUE(finite.isFinite());
}

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

    limits = ZLimits::unite(limitless, limitless);
    EXPECT_EQ(limitless, limits);

    limits = ZLimits::unite(limitless, poslimit1);
    EXPECT_EQ(limitless, limits);
    limits = ZLimits::unite(poslimit1, limitless);
    EXPECT_EQ(limitless, limits);

    limits = ZLimits::unite(limitless, neglimit1);
    EXPECT_EQ(limitless, limits);
    limits = ZLimits::unite(neglimit1, limitless);
    EXPECT_EQ(limitless, limits);

    limits = ZLimits::unite(limitless, finite1);
    EXPECT_EQ(limitless, limits);
    limits = ZLimits::unite(finite1, limitless);
    EXPECT_EQ(limitless, limits);

    limits = ZLimits::unite(poslimit1, poslimit2);
    EXPECT_EQ(poslimit1, limits);
    limits = ZLimits::unite(poslimit2, poslimit1);
    EXPECT_EQ(poslimit1, limits);

    limits = ZLimits::unite(poslimit1, neglimit1);
    EXPECT_EQ(limitless, limits);
    limits = ZLimits::unite(neglimit1, poslimit1);
    EXPECT_EQ(limitless, limits);

    limits = ZLimits::unite(neglimit1, neglimit2);
    EXPECT_EQ(neglimit2, limits);
    limits = ZLimits::unite(neglimit2, neglimit1);
    EXPECT_EQ(neglimit2, limits);

    limits = ZLimits::unite(finite1, finite2);
    EXPECT_EQ(ZLimits(-3, 6), limits);
    limits = ZLimits::unite(finite2, finite1);
    EXPECT_EQ(ZLimits(-3, 6), limits);

    limits = ZLimits::unite(finite1, finite3);
    EXPECT_EQ(ZLimits(-3, 15), limits);
    limits = ZLimits::unite(finite3, finite1);
    EXPECT_EQ(ZLimits(-3, 15), limits);
}
