#ifndef __JLANG__JBIDIRECTIONALITERATOR__
#define __JLANG__JBIDIRECTIONALITERATOR__

#include "JLang/JForwardIterator.hh"

/**
 * \author mdejong
 */

namespace JLANG {}
namespace JPP { using namespace JLANG; }

namespace JLANG {

  /**
   * Template interface for method bool decrement().
   * This interface implements the pre-fix and post-fix operators --.
   */
  template<class T> 
  class JBidirectionalIterator :
    public JForwardIterator<T>
  {
  public:
    /**
     * Virtual destructor.
     */
    virtual ~JBidirectionalIterator()
    {}


    /**
     * Decrement iterator.
     *
     * \return                 this iterator
     */
    T& operator--()
    {
      this->decrement();

      return static_cast<T&>(*this);
    }
    

    /**
     * Decrement iterator.
     *
     * \return                 decrement iterator
     */
    T operator--(int)
    {
      const T tmp(static_cast<const T&>(*this));

      this->decrement();

      return tmp;
    }


    /**
     * Regress iterator.
     *
     * \param  offset          offset
     * \return                 iterator
     */
    T& operator-=(const size_t offset)
    {
      this->decrement(offset);

      return static_cast<T&>(*this);
    }


    /**
     * Regress operator.
     *
     * \param  object          iterator
     * \param  offset          offset
     * \return                 iterator
     */
    friend inline T operator-(const T& object, const size_t offset)
    {
      T tmp(object);

      tmp.decrement(offset);

      return tmp;
    }


    /**
     * Decrement iterator.
     *
     * \return                 true if decremented; else false
     */
    virtual bool decrement() = 0;


    /**
     * Decrement iterator.
     *
     * \param  offset          offset
     * \return                 true if decremented; else false
     */
    virtual bool decrement(const size_t offset)
    {
      size_t i = 0;

      while (i != offset && this->decrement()) {
        ++i;
      }

      return i == offset;
    }
  };
}

#endif