#include "Base/Axis/FixedBinAxis.h"
#include "Base/Axis/VariableBinAxis.h"
#include "Base/Const/Units.h"
#include "GUI/coregui/Models/AxesItems.h"
#include "GUI/coregui/Models/PropertyItem.h"
#include "GUI/coregui/Models/TransformFromDomain.h"
#include "GUI/coregui/utils/GUIHelpers.h"
#include "Tests/GTestWrapper/google_test.h"

class TestAxesItems : public ::testing::Test {
};

TEST_F(TestAxesItems, gettersAndSettes)
{
    BasicAxisItem item;

    item.setBinCount(42);
    EXPECT_EQ(item.binCount(), 42);

    item.setLowerBound(42.1);
    EXPECT_EQ(item.lowerBound(), 42.1);

    item.setUpperBound(42.2);
    EXPECT_EQ(item.upperBound(), 42.2);

    item.setTitle("abc");
    EXPECT_EQ(item.title(), QString("abc"));
}

TEST_F(TestAxesItems, AmplitudeAxisGettersAndSetters)
{
    AmplitudeAxisItem item;

    item.setLogScale(true);
    EXPECT_TRUE(item.isLogScale());
    item.setLogScale(false);
    EXPECT_FALSE(item.isLogScale());
}

TEST_F(TestAxesItems, transformFromDomain)
{
    BasicAxisItem item;

    // transform domain axis without scale factor
    FixedBinAxis axis0("axis0", 99, -42.0, 42.0);
    TransformFromDomain::setAxisItem(&item, axis0);
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_NBINS), static_cast<int>(axis0.size()));
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_MIN_DEG), static_cast<int>(axis0.lowerBound()));
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_MAX_DEG), static_cast<int>(axis0.upperBound()));
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_TITLE), QString::fromStdString(axis0.getName()));

    // transform domain axis with limits given in radians
    FixedBinAxis axis1("axis1", 42, -42.0 * Units::deg, 42.0 * Units::deg);
    const double scale = 1. / Units::deg;
    TransformFromDomain::setAxisItem(&item, axis1, scale);
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_NBINS), static_cast<int>(axis1.size()));
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_MIN_DEG), -42.0);
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_MAX_DEG), 42.0);
    EXPECT_EQ(item.getItemValue(BasicAxisItem::P_TITLE), QString::fromStdString(axis1.getName()));

    // transform to unexpected item
    PropertyItem property;
    EXPECT_THROW(TransformFromDomain::setAxisItem(&property, axis1), GUIHelpers::Error);

    // transform from unexpected axis
    std::vector<double> bins = {1.0, 2.0, 3.0};
    VariableBinAxis varaxis("axis", bins.size() - 1, bins);
    EXPECT_THROW(TransformFromDomain::setAxisItem(&item, varaxis), GUIHelpers::Error);
}
