//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sample/Option/SimulationOptions.h
//! @brief     Defines class SimulationOptions.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifndef BORNAGAIN_SAMPLE_OPTION_SIMULATIONOPTIONS_H
#define BORNAGAIN_SAMPLE_OPTION_SIMULATIONOPTIONS_H

#include "Base/Math/Integrator.h"
#include <cstddef>

using std::size_t;

//! Options to compute mesocrystal formfactors.

struct MesoOptions {
    bool use_reciprocal_sum{false}; //!< If true, use approximative but faster algorithm
    double radius_factor{2.1};      //!< Cutoff for fast (reciprocal-sum) algorithm
};

//! Collect the different options for simulation.
//! @ref SimulationOptions

class SimulationOptions {
public:
    SimulationOptions();

    //! Enables/disables MonteCarlo integration
    //! @param flag If true, MonteCarlo integration will be used, otherwise analytical calculations
    //! @param mc_points Number of points for MonteCarlo integrator
    void setMonteCarloIntegration(bool flag = true, size_t mc_points = 50);

    //! Sets number of threads to use during the simulation (0 - take default value from hardware)
    void setNumberOfThreads(int nthreads);

    //! Sets number of batches to split
    void setNumberOfBatches(int nbatches); // TODO: undocumented, probably useless

    void setIncludeSpecular(bool include_specular) { m_include_specular = include_specular; }

    void setUseAvgMaterials(bool use_avg_materials) { m_use_avg_materials = use_avg_materials; }

    void setMesoReciprocalSum(bool use_rec_sum, double rad_factor);

    void setOffspecIntegratorOptions(const std::string& type,
                                     const std::map<std::string, double>& pars);

#ifndef SWIG

    bool isIntegrate() const;
    size_t mcPoints() const { return m_mc_points; }
    unsigned numberOfThreads() const;
    unsigned numberOfBatches() const;
    unsigned currentBatch() const;
    unsigned hardwareConcurrency() const;
    bool includeSpecular() const { return m_include_specular; }
    bool useAvgMaterials() const { return m_use_avg_materials; }
    MesoOptions mesoReciprocalSum() const { return m_meso_options; }
    IntegratorOptions offspecIntegratorOptions() const { return m_offspec_integrator_options; }

private:
    bool m_mc_integration;
    bool m_include_specular;
    bool m_use_avg_materials;
    MesoOptions m_meso_options;
    IntegratorOptions m_offspec_integrator_options;
    size_t m_mc_points;
    unsigned m_n_threads{0};
    unsigned m_n_batches{1};
    unsigned m_current_batch{0};
#endif // SWIG
};

#endif // BORNAGAIN_SAMPLE_OPTION_SIMULATIONOPTIONS_H
