#include "Base/Const/Units.h"
#include "Device/Detector/IDetector.h"
#include "Device/Resolution/ConvolutionDetectorResolution.h"
#include "Device/Resolution/ResolutionFunction2DGaussian.h"
#include "GUI/Model/Detector/RectangularDetectorItem.h"
#include "GUI/Model/Detector/ResolutionFunctionItems.h"
#include "GUI/Model/Detector/SphericalDetectorItem.h"
#include "GUI/Model/Device/BackgroundItems.h"
#include "GUI/Model/Device/InstrumentItems.h"
#include "GUI/Model/Device/InstrumentModel.h"
#include "GUI/Support/Type/Unit.h"
#include "Tests/GTestWrapper/google_test.h"

TEST(TestDetectorItems, resolutionFunction)
{
    InstrumentModel model;
    auto* instrument = model.addInstrumentItem<GISASInstrumentItem>();

    DetectorItem* detectorItem = instrument->detectorItem();

    detectorItem->setResolutionFunctionType<ResolutionFunction2DGaussianItem>();

    auto detector = detectorItem->createDetector();
    const auto* convol =
        dynamic_cast<const ConvolutionDetectorResolution*>(detector->detectorResolution());
    const auto* gaussian =
        dynamic_cast<const ResolutionFunction2DGaussian*>(convol->getResolutionFunction2D());

    EXPECT_EQ(Units::rad2deg(gaussian->sigmaX()), 0.02);
}

TEST(TestDetectorItems, resolutionFunctionUnit)
{
    const auto asString = [](const std::variant<QString, Unit>& unit) {
        return std::holds_alternative<QString>(unit) ? std::get<QString>(unit)
                                                     : unitAsString(std::get<Unit>(unit));
    };

    RectangularDetectorItem detector;
    detector.setResolutionFunctionType<ResolutionFunctionNoneItem>();
    detector.setResolutionFunctionType<ResolutionFunction2DGaussianItem>();
    auto* p = dynamic_cast<ResolutionFunction2DGaussianItem*>(
        detector.resolutionFunctionSelection().currentItem());
    EXPECT_NE(p, nullptr);
    EXPECT_EQ(asString(p->sigmaX().unit()), "mm");
    EXPECT_EQ(asString(p->sigmaY().unit()), "mm");

    SphericalDetectorItem sphericalDetector;
    sphericalDetector.setResolutionFunctionType<ResolutionFunctionNoneItem>();
    sphericalDetector.setResolutionFunctionType<ResolutionFunction2DGaussianItem>();
    p = dynamic_cast<ResolutionFunction2DGaussianItem*>(
        sphericalDetector.resolutionFunctionSelection().currentItem());
    EXPECT_NE(p, nullptr);
    EXPECT_EQ(asString(p->sigmaX().unit()), unitAsString(Unit::degree));
    EXPECT_EQ(asString(p->sigmaY().unit()), unitAsString(Unit::degree));
}
