//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sim/Scan/IBeamScan.cpp
//! @brief     Implements interface IBeamScan.
//!
//! @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 "Sim/Scan/IBeamScan.h"
#include "Base/Axis/Scale.h"
#include "Base/Spin/SpinMatrix.h"
#include "Device/Beam/IFootprint.h"
#include "Device/Pol/PolFilter.h"
#include <iostream>

IBeamScan::IBeamScan(Scale* axis, double lambda0)
    : m_axis(axis)
    , m_lambda0(lambda0)
{
}

IBeamScan::~IBeamScan() = default;

std::vector<const INode*> IBeamScan::nodeChildren() const
{
    std::vector<const INode*> result;
    if (m_footprint)
        result << m_footprint.get();
    if (m_polAnalyzer)
        result << m_polAnalyzer.get();
    return result;
}

void IBeamScan::setWavelength(double lambda0)
{
    m_lambda0 = lambda0;
}

void IBeamScan::setIntensity(double intensity)
{
    m_intensity = intensity;
}

void IBeamScan::setPolarization(R3 bloch_vector)
{
    m_beamPolarization.reset(new R3(bloch_vector));
}

void IBeamScan::setAnalyzer(R3 Bloch_vector, double mean_transmission)
{
    m_polAnalyzer.reset(new PolFilter(Bloch_vector, mean_transmission));
}

void IBeamScan::setAnalyzer(R3 direction, double efficiency, double mean_transmission)
{
    std::cout
        << "Function setAnalyzer(direction, efficiency, transmission) is obsolete since "
           "BornAgain v21,\n"
           "and will eventually be removed. Use setAnalyzer(Bloch_vector, transmission) instead.\n";
    setAnalyzer(direction * efficiency, mean_transmission);
}

void IBeamScan::setFootprint(const IFootprint* footprint)
{
    m_footprint.reset(footprint ? footprint->clone() : nullptr);
}

size_t IBeamScan::nScan() const
{
    return m_axis->size();
}

bool IBeamScan::polarized() const
{
    return m_beamPolarization || m_polAnalyzer;
}

SpinMatrix IBeamScan::polarizerMatrix() const
{
    return m_beamPolarization ? SpinMatrix::FromBlochVector(*m_beamPolarization)
                              : SpinMatrix::One() / 2.;
}

SpinMatrix IBeamScan::analyzerMatrix() const
{
    return m_polAnalyzer ? m_polAnalyzer->matrix() : SpinMatrix::One();
}
