//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Resample/Element/SpecularElement.cpp
//! @brief     Implements the class SpecularElement.
//!
//! @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)
//
//  ************************************************************************************************

#include "Resample/Element/SpecularElement.h"
#include "Base/Vector/GisasDirection.h"
#include "Resample/Slice/KzComputation.h"

SpecularElement SpecularElement::FromQzScan(size_t i_out, double weight, double kz,
                                            const SpinMatrix& polarizer, const SpinMatrix& analyzer,
                                            bool computable)
{
    return {i_out, computable, weight, 1, polarizer, analyzer, [kz](const SliceStack& slices) {
                return Compute::Kz::computeKzFromSLDs(slices, kz);
            }};
}

SpecularElement SpecularElement::FromAlphaScan(size_t i_out, double weight, double wavelength,
                                               double alpha, double footprint,
                                               const SpinMatrix& polarizer,
                                               const SpinMatrix& analyzer, bool computable)
{
    return {i_out,
            computable,
            weight,
            footprint,
            polarizer,
            analyzer,
            [k = vecOfLambdaAlphaPhi(wavelength, alpha)](const SliceStack& slices) {
                return Compute::Kz::computeKzFromRefIndices(slices, k);
            }};
}

SpecularElement::SpecularElement(size_t i_out, bool computable, double weight, double footprint,
                                 const SpinMatrix& polarizer, const SpinMatrix& analyzer,
                                 std::function<std::vector<complex_t>(const SliceStack&)> kz_comp)
    : IElement(polarizer, analyzer)
    , m_i_out(i_out)
    , m_weight(weight)
    , m_footprint(footprint)
    , m_computable(computable)
    , m_kz_computation(kz_comp)
{
}

SpecularElement::~SpecularElement() = default;

std::vector<complex_t> SpecularElement::produceKz(const SliceStack& slices)
{
    return m_kz_computation(slices);
}
