//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sample/Material/Admixtures.h
//! @brief     Defines class OneAdmixture, and declares fct createAveragedMaterial.
//!
//! @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)
//
//  ************************************************************************************************

#ifdef SWIG
#error no need to expose this header to Swig
#endif // SWIG
#ifndef BORNAGAIN_SAMPLE_MATERIAL_ADMIXTURES_H
#define BORNAGAIN_SAMPLE_MATERIAL_ADMIXTURES_H

#include "Sample/Material/Material.h"
#include <memory>
#include <vector>

//! A component in a mixture, consisting of a given volume of a homogeneous material.
//! The absolute scale of the volume is irrelevant; only the relative weights matter.

class OneAdmixture {
public:
    OneAdmixture(double volume, const Material& material);
    OneAdmixture(const OneAdmixture& other);

    double volume() const { return m_volume; }
    const Material* material() const { return m_material.get(); }

private:
    double m_volume; //!< Volume (weight)
    const std::unique_ptr<const Material> m_material;
};

namespace MixUtil {

//! Returns material with averaged properties.
//! When mixing SLD and refractive-index materials, a reference wavelength (in nm) is used
//! to convert refractive indices to SLD. The result is an SLDMaterial.
std::unique_ptr<const Material> averagedMaterial(const std::string& name,
                                                 const std::vector<OneAdmixture>& admixtures,
                                                 double ref_wavelength = 0.1);

//! Returns material with averaged properties.
//! `base_volume` is the total volume (weight) that `base_mat` would occupy without admixtures.
//! The base material will occupy the remaining volume, `base_volume - sum(admixture volumes)`.
std::unique_ptr<const Material> basePlusAdmixtures(const Material& base_mat, double base_volume,
                                                   std::vector<OneAdmixture> admixtures,
                                                   double ref_wavelength = 0.1);
} // namespace MixUtil

#endif // BORNAGAIN_SAMPLE_MATERIAL_ADMIXTURES_H
