#ifndef INCLUDED_BOBCAT_ITERATOR_
#define INCLUDED_BOBCAT_ITERATOR_

#include <iterator>
#include <limits>
#include <memory>

namespace FBB
{

template <typename Type>
class Iterator;

template <typename Type>
struct ReverseIterator: public std::reverse_iterator<Iterator<Type>>
{
    explicit ReverseIterator(Type const &value);
    explicit ReverseIterator(Iterator<Type> const &iter);

    static ReverseIterator<Type> last(Type const &value);
};

template <typename Type>
bool operator==(Iterator<Type> const &lhs, Iterator<Type> const &rhs);

template <typename Type>
struct Iterator
{
    friend  bool operator==<>(Iterator<Type> const &lhs,
                            Iterator<Type> const &rhs);

    using iterator_category = std::input_iterator_tag;
    using difference_type   = std::ptrdiff_t;
    using value_type        = Type const;
    using pointer           = value_type *;
    using reference         = value_type &;

    private:
        Type d_value;
        std::shared_ptr<Type> d_type;

    public:
        Iterator() = default;
        explicit Iterator(Type const &value);

        Iterator<Type> &operator++();
        Iterator<Type> operator++(int);

        Type const &operator*() const;

        static Iterator<Type> last(Type value);
        static Iterator<Type> min();
        static Iterator<Type> max();

    private:
        friend struct std::reverse_iterator<Iterator<Type>>;

        Iterator<Type> &operator--();
        Iterator<Type> operator--(int);
};


#include "iterator1.f"
#include "last.f"
#include "max.f"
#include "min.f"
#include "operatordec.f"
#include "operatorequal.f"
#include "operatorinc.f"
#include "operatorpostdec.f"
#include "operatorpostinc.f"
#include "operatorstarconst.f"
#include "operatorunequal.f"
#include "reverseiterator1.f"
#include "reverseiterator2.f"
#include "reverseiteratorlast.f"

} // FBB

#endif
