#ifndef REVERSE_ITERATOR_HPP
# define REVERSE_ITERATOR_HPP

# include <iterator> // iterator_tag
# include "iterator_traits.hpp"

namespace ft {

template < class Iter >
class reverse_iterator {

private:

	Iter								_it;
	typedef ft::iterator_traits<Iter>	_traits;

public:
	typedef Iter								iterator_type;
	typedef typename _traits::iterator_category	iterator_category;
	typedef typename _traits::value_type		value_type;
	typedef typename _traits::difference_type	difference_type;
	typedef typename _traits::pointer			pointer;
	typedef typename _traits::reference			reference;


	/****************
	 * constructors :
	 ****************/
	reverse_iterator()
		: _it()
		{}
	explicit reverse_iterator(iterator_type it)
		: _it(it)
		{}	
//	reverse_iterator(const reverse_iterator& src)
//		: _it(src._it)
//		{}
	template < class Iterator >
		reverse_iterator(const reverse_iterator<Iterator>& rev_it)
		: _it(rev_it.base())
		{}

	/*********************
	 * members functions :
	 *********************/
// base -------------------------------------- 
	iterator_type base() const
		{ return _it; }
// operator * -------------------------------- 
	reference operator*() const
		{ Iter tmp = _it; return *--tmp; }
// operator + -------------------------------- 
	reverse_iterator operator+(difference_type n) const
		{ return reverse_iterator(_it - n); }
// operator ++ ------------------------------- 
	reverse_iterator operator++(int)
		{ reverse_iterator old(*this); ++(*this); return old; }
	reverse_iterator & operator++()
		{ --_it; return *this; }
// operator += ------------------------------- 
	reverse_iterator & operator+=(difference_type n)
		{ _it -= n; return *this; }
// operator - -------------------------------- 
	reverse_iterator operator-(difference_type n) const 
		{ return reverse_iterator(_it + n); }
// operator -- ------------------------------- 
	reverse_iterator operator--(int)
		{ reverse_iterator old(*this); --(*this); return old; }
	reverse_iterator & operator--()
		{ ++_it; return *this; }
// operator -= ------------------------------- 
	reverse_iterator & operator-=(difference_type n)
		{ _it += n; return *this; }
// operator -> ------------------------------- 
	pointer operator->() const
		{ return &(operator*()); }
// operator [] ------------------------------- 
	reference operator[] (difference_type n) const
		{ return _it[-n-1]; }
};

	/*************************
	 * non-members functions :
	 *************************/
// operator == ------------------------------- 
template <class Iterator>
	bool operator== (const reverse_iterator<Iterator>& lhs,
					 const reverse_iterator<Iterator>& rhs)
	{ return lhs.base() == rhs.base(); }
// operator != ------------------------------- 
template <class Iterator>
	bool operator!= (const reverse_iterator<Iterator>& lhs,
					 const reverse_iterator<Iterator>& rhs)
	{ return lhs.base() != rhs.base(); }
// operator < -------------------------------- 
template <class Iterator>
	bool operator<  (const reverse_iterator<Iterator>& lhs,
					 const reverse_iterator<Iterator>& rhs)
	{ return lhs.base() > rhs.base(); }
// operator <= ------------------------------- 
template <class Iterator>
	bool operator<= (const reverse_iterator<Iterator>& lhs,
					 const reverse_iterator<Iterator>& rhs)
	{ return lhs.base() >= rhs.base(); }
// operator > -------------------------------- 
template <class Iterator>
	bool operator>  (const reverse_iterator<Iterator>& lhs,
					 const reverse_iterator<Iterator>& rhs)
	{ return lhs.base() < rhs.base(); }
// operator >= ------------------------------- 
template <class Iterator>
	bool operator>= (const reverse_iterator<Iterator>& lhs,
					 const reverse_iterator<Iterator>& rhs)
	{ return lhs.base() <= rhs.base(); }


	/*******************
	 * other operators :
	 *******************/
// operator + non-member overload ------------ 
template <class Iterator>
	reverse_iterator<Iterator> operator+
		(typename reverse_iterator<Iterator>::difference_type n
		,const reverse_iterator<Iterator>& rhs)
	{ return reverse_iterator<Iterator>(rhs.base() - n); }

// operator - non-member overload ------------ 
template <class Iterator>
	typename reverse_iterator<Iterator>::difference_type operator-
		(const reverse_iterator<Iterator>& lhs
		,const reverse_iterator<Iterator>& rhs)
	{ return rhs.base() - lhs.base(); }




} // namespace ft

#endif

