//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Device/Detector/OffspecDetector.h
//! @brief     Defines class OffspecDetector.
//!
//! @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_DEVICE_DETECTOR_OFFSPECDETECTOR_H
#define BORNAGAIN_DEVICE_DETECTOR_OFFSPECDETECTOR_H

#include "Base/Axis/Bin.h"
#include "Base/Axis/Scale.h"
#include "Base/Type/Cloneable.h"
#include <heinz/Vectors3D.h>

class DetectorResolution;
class Pixel;
class PolFilter;
class SpinMatrix;

//! A phi-integrating detector with coordinate axis along alpha.

class OffspecDetector : public Cloneable {
public:
    //! Returns a detector with given phi and alpha axes.
    //! @param phi_min low edge of first phi-bin
    //! @param phi_max upper edge of last phi-bin
    //! @param n_alpha number of alpha-axis bins
    //! @param alpha_min low edge of first alpha-bin
    //! @param alpha_max upper edge of last alpha-bin
    OffspecDetector(size_t n_alpha, double alpha_min, double alpha_max, double phi_min,
                    double phi_max);

    ~OffspecDetector() override;

    //! Sets the polarization analyzer characteristics of the detector
    void setAnalyzer(const R3& direction, double transmission_selected = 1,
                     double transmission_suppressed = 0);

#ifndef SWIG
    OffspecDetector* clone() const override;

    //! Vertical axis of the detector.
    const Scale& alphaAxis() const { return m_alpha_axis; }

    //! Horizontal range of the detector.
    const Bin1D& phiRange() const { return m_phi_range; }

    //! Creates an Pixel for the given alpha index and phi-value
    std::unique_ptr<Pixel> createPixel(size_t alpha_index, double phi) const;

    //! Returns index of alpha-pixel that contains the specular wavevector.
    //! If no pixel contains this specular wavevector, the number of pixels is
    //! returned. This corresponds to an overflow index.
    size_t aplhaIndexOfSpecular(double alpha_spec, double phi_spec) const;

    //! Returns detection properties
    const PolFilter* analyzer() const { return m_pol_analyzer.get(); }
    SpinMatrix analyzerMatrix() const;

private:
    Scale m_alpha_axis;
    Bin1D m_phi_range;
    std::unique_ptr<PolFilter> m_pol_analyzer;
    // TODO now unused, restore https://jugit.fz-juelich.de/mlz/bornagain/-/issues/1113
    // std::unique_ptr<DetectorResolution> m_resolution;
#endif // SWIG
};

#endif // BORNAGAIN_DEVICE_DETECTOR_OFFSPECDETECTOR_H
