#ifndef BORNAGAIN_TESTS_UNIT_SIM_FITTINGTESTHELPER_H
#define BORNAGAIN_TESTS_UNIT_SIM_FITTINGTESTHELPER_H

#include "Base/Axis/MakeScale.h"
#include "Base/Const/Units.h"
#include "Device/Beam/Beam.h"
#include "Device/Data/Datafield.h"
#include "Device/Detector/SphericalDetector.h"
#include "Fit/Param/Parameters.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sample/Multilayer/Layer.h"
#include "Sample/Multilayer/Sample.h"
#include "Sim/Simulation/ScatteringSimulation.h"
#include <memory>

//! Helper class to simplify testing of SimDataPair and FitObjective

class FittingTestHelper {
public:
    FittingTestHelper(size_t nx = 5, size_t ny = 5)
        : m_nx(nx)
        , m_ny(ny)
        , m_builder_calls(0)
    {
    }

    size_t m_nx;
    size_t m_ny;
    const double m_xmin = -1 * Units::deg;
    const double m_xmax = 4 * Units::deg;
    const double m_ymin = 0 * Units::deg;
    const double m_ymax = 4 * Units::deg;

    size_t m_builder_calls;

    std::unique_ptr<ISimulation> createSimulation(const mumufit::Parameters&)
    {
        Sample sample;
        auto material = RefractiveMaterial("Shell", 0.0, 0.0);
        sample.addLayer(Layer(material));
        sample.addLayer(Layer(material));

        SphericalDetector detector(m_nx, m_xmin, m_xmax, m_ny, m_ymin, m_ymax);
        std::unique_ptr<ScatteringSimulation> result(
            new ScatteringSimulation(Beam(1., 1., 0.), sample, detector));

        m_builder_calls++;
        return std::unique_ptr<ISimulation>(result.release());
    }

    std::unique_ptr<Datafield> createTestData(double value)
    {
        std::unique_ptr<Datafield> result(new Datafield(
            std::vector<const Scale*>{newEquiDivision("phi_f (rad)", m_nx, m_xmin, m_xmax),
                                      newEquiDivision("alpha_f (rad)", m_ny, m_ymin, m_ymax)}));
        result->setAllTo(value);
        return result;
    }

    size_t size() const { return m_nx * m_ny; }
};

#endif // BORNAGAIN_TESTS_UNIT_SIM_FITTINGTESTHELPER_H
