#include "Base/Const/Units.h"

#include "Device/Beam/Beam.h"
#include "Device/Beam/FootprintGauss.h"
#include "Device/Beam/FootprintSquare.h"
#include "Tests/GTestWrapper/google_test.h"
#include <limits>
#include <memory>

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

TEST(BeamFootprint, ErroneousArguments)
{
    EXPECT_THROW(FootprintGauss(-1.0), std::runtime_error);
    EXPECT_THROW(FootprintSquare(-1.0), std::runtime_error);

    FootprintGauss gaussian_ff(inf);
    EXPECT_EQ(0.0, gaussian_ff.calculate(-90.0 * Units::deg));

    FootprintSquare square_ff(inf);
    EXPECT_EQ(0.0, square_ff.calculate(-90.0 * Units::deg));
}

TEST(BeamFootprint, CalcForRegularCases)
{
    FootprintGauss gaussian_ff(1.0 / std::sqrt(2.0));

    EXPECT_EQ(0.0, gaussian_ff.calculate(0.0));
    EXPECT_NEAR(0.84270079295, gaussian_ff.calculate(90.0 * Units::deg), 1e-10);

    FootprintSquare square_ff(2.0);

    EXPECT_EQ(0.0, square_ff.calculate(0.0));
    EXPECT_EQ(0.5, square_ff.calculate(90.0 * Units::deg));
}

TEST(BeamFootprint, Clone)
{
    FootprintGauss gaussian_ff(1.0);
    std::unique_ptr<FootprintGauss> gaussian_clone(gaussian_ff.clone());

    EXPECT_NE(gaussian_clone.get(), &gaussian_ff);
    EXPECT_EQ(gaussian_clone->widthRatio(), gaussian_ff.widthRatio());

    FootprintSquare square_ff(1.0);
    std::unique_ptr<FootprintSquare> square_clone(square_ff.clone());

    EXPECT_NE(square_clone.get(), &square_ff);
    EXPECT_EQ(square_clone->widthRatio(), square_ff.widthRatio());
}
