//#####################################################################
// Copyright 2004-2009, Kevin Der, Ronald Fedkiw, Geoffrey Irving, Frank Losasso, Craig Schroeder, Andrew Selle, Tamar Shinar, Eftychios Sifakis, Jerry Talton, Wen Zheng.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class SIMPLE_ITERATOR
//#####################################################################
#ifndef __SIMPLE_ITERATOR__
#define __SIMPLE_ITERATOR__
namespace PhysBAM{

template<class T_ARRAY>
class SIMPLE_ITERATOR
{
private:
    struct UNUSABLE{};
public:
    typedef conditional_t<std::is_const_v<T_ARRAY>,std::remove_const_t<T_ARRAY>,UNUSABLE> C_ARRAY;
    typedef conditional_t<std::is_const_v<T_ARRAY>,typename T_ARRAY::CONST_RESULT_TYPE,typename T_ARRAY::RESULT_TYPE> RESULT_TYPE;
    typedef typename T_ARRAY::CONST_RESULT_TYPE CONST_RESULT_TYPE;

    T_ARRAY& array;
    typename T_ARRAY::INDEX index;

    SIMPLE_ITERATOR(const SIMPLE_ITERATOR& s)=default;

    SIMPLE_ITERATOR(const SIMPLE_ITERATOR<C_ARRAY>& s)
        :array(s.array),index(s.index)
    {}
    
    SIMPLE_ITERATOR(T_ARRAY& array,typename T_ARRAY::INDEX index)
        :array(array),index(index)
    {}

    RESULT_TYPE operator*()
    {return array(index);}

    CONST_RESULT_TYPE operator*() const
    {return array(index);}

    auto operator->()
    {return &array(index);}

    auto operator->() const
    {return &array(index);}

    // stl
    SIMPLE_ITERATOR& operator++()
    {index++;return *this;}

    SIMPLE_ITERATOR operator++(int)
    {SIMPLE_ITERATOR it(*this);index++;return it;}

    // stl
    SIMPLE_ITERATOR& operator--()
    {index--;return *this;}

    SIMPLE_ITERATOR operator--(int)
    {SIMPLE_ITERATOR it(*this);index--;return it;}

    template<class T_ARRAY1> bool operator==(const SIMPLE_ITERATOR<T_ARRAY1>& it) const
    {return index==it.index;}

    template<class T_ARRAY1> bool operator!=(const SIMPLE_ITERATOR<T_ARRAY1>& it) const
    {return index!=it.index;}

    template<class T_ARRAY1> bool operator<(const SIMPLE_ITERATOR<T_ARRAY1>& it) const
    {return index<it.index;}

    template<class T_ARRAY1> bool operator>(const SIMPLE_ITERATOR<T_ARRAY1>& it) const
    {return index>it.index;}

    template<class T_ARRAY1> bool operator<=(const SIMPLE_ITERATOR<T_ARRAY1>& it) const
    {return index<=it.index;}

    template<class T_ARRAY1> bool operator>=(const SIMPLE_ITERATOR<T_ARRAY1>& it) const
    {return index>=it.index;}

};
}
#endif
