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

#include <cstdlib>

class IDetector;

//! An iterator for SimulationArea.

class SimulationAreaIterator {
private:
    explicit SimulationAreaIterator(const IDetector* detector, size_t start_at_index);

public:
    //! Create begin-iterator to iterate over all points according to the given mode.
    static SimulationAreaIterator createBegin(const IDetector* detector);

    //! Create end-iterator to iterate over all points according to the given mode.
    static SimulationAreaIterator createEnd(const IDetector* detector);

    //! Convenience function to create an end-iterator matching to this iterator.
    SimulationAreaIterator createEnd() const;

    size_t roiIndex() const;
    size_t detectorIndex() const;

    bool operator==(const SimulationAreaIterator& other) const;
    bool operator!=(const SimulationAreaIterator& right) const;

    //! prefix increment
    SimulationAreaIterator& operator++();

private:
    size_t nextIndex(size_t currentIndex);

    bool isMasked(size_t index) const;

    const IDetector* m_detector;
    size_t m_index;    //!< ROI related index
    size_t m_maxIndex; //!< ROI related maximum index
};

inline bool SimulationAreaIterator::operator==(const SimulationAreaIterator& other) const
{
    return m_detector == other.m_detector && m_index == other.m_index;
}

inline bool SimulationAreaIterator::operator!=(const SimulationAreaIterator& right) const
{
    return !(*this == right);
}

#endif // BORNAGAIN_DEVICE_DETECTOR_SIMULATIONAREAITERATOR_H
