#include "Base/Axis/MakeScale.h"

#include "Base/Axis/Scale.h"
#include "Param/Distrib/Distributions.h"
#include "Param/Distrib/ParameterSample.h"
#include "Resample/Slice/SliceStack.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sim/Scan/AlphaScan.h"
#include "Sim/Scan/QzScan.h"
#include "Tests/GTestWrapper/google_test.h"

TEST(SpecularScanTest, AngularScanClone)
{
    AlphaScan scan(3, 0.1, 0.3);
    scan.setWavelength(0.123);
    EXPECT_EQ(scan.wavelength(), 0.123);

    std::unique_ptr<AlphaScan> scan_clone(scan.clone());
    EXPECT_EQ(*scan_clone->coordinateAxis(), *scan.coordinateAxis());
    EXPECT_NE(scan_clone->coordinateAxis(), scan.coordinateAxis());
    EXPECT_EQ(scan_clone->wavelength(), scan.wavelength());

    std::unique_ptr<AlphaScan> scan_clone2(scan.clone());
    EXPECT_EQ(*scan_clone2->coordinateAxis(), *scan.coordinateAxis());
    EXPECT_EQ(scan_clone2->wavelength(), scan.wavelength());
}

TEST(SpecularScanTest, QScanClone)
{
    QzScan scan(std::vector<double>{0.1, 0.2, 0.3});
    scan.setOffset(2.22);
    const auto distribution = DistributionGaussian(.4711, 1., 25, 3.);
    scan.setRelativeQResolution(distribution, 0.02);

    std::unique_ptr<QzScan> scan_clone(scan.clone());
    EXPECT_EQ(*scan_clone->coordinateAxis(), *scan.coordinateAxis());
    EXPECT_NE(scan_clone->coordinateAxis(), scan.coordinateAxis());

    const auto* resolution = scan.qzDistribution();
    const auto* distributionClone = dynamic_cast<const DistributionGaussian*>(resolution);
    EXPECT_NE(distributionClone, nullptr);
    EXPECT_NE(distributionClone, &distribution);
    if (distributionClone) {
        EXPECT_EQ(distributionClone->relSamplingWidth(), 3.);
        EXPECT_EQ(distributionClone->nSamples(), 25);
    }
}

TEST(SpecularScanTest, ErrorInput)
{
    EXPECT_THROW(QzScan(std::vector<double>{-0.01, 0.2, 0.3}), std::runtime_error);
    EXPECT_THROW(QzScan(std::vector<double>{0.1, 0.3, 0.2}), std::runtime_error);
}
