// Copyright (c) 2014  GeometryFactory (France).  All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 3 of the License,
// or (at your option) any later version.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL$
// $Id$
// 
//
// Author(s)     : Andreas Fabri

#ifndef CGAL_BGL_ITERATORS_H
#define CGAL_BGL_ITERATORS_H

#include <stdexcept>

#include <boost/graph/graph_traits.hpp>
#include <boost/iterator/transform_iterator.hpp>

#include <CGAL/assertions.h>
#include <CGAL/circulator_bases.h>
#include <CGAL/boost/graph/internal/helpers.h>

namespace CGAL {


namespace internal {

template <typename G>
struct Edge {
  const G* g; 

  Edge()
    : g(NULL)
  {}

  Edge(const G& g)
    : g(&g)
  {}

  typedef typename boost::graph_traits<G>::edge_descriptor result_type;
  typedef typename boost::graph_traits<G>::halfedge_descriptor argument_type;

  result_type operator()(argument_type h) const
  {
    return edge(h, *g);
  }
};

template <typename G>
struct OppositeEdge {
  const G* g; 

  OppositeEdge()
    : g(NULL)
  {}

  OppositeEdge(const G& g)
    : g(&g)
  {}

  typedef typename boost::graph_traits<G>::edge_descriptor result_type;
  typedef typename boost::graph_traits<G>::halfedge_descriptor argument_type;

  result_type operator()(argument_type h) const
  {
    return edge(opposite(h,*g), *g);
  }
};

template <typename G>
struct OppositeHalfedge {
  const G* g; 

  OppositeHalfedge()
    : g(NULL)
  {}

  OppositeHalfedge(const G& g)
    : g(&g)
  {}

  typedef typename boost::graph_traits<G>::halfedge_descriptor result_type;
  typedef typename boost::graph_traits<G>::halfedge_descriptor argument_type;

  result_type operator()(argument_type h) const
  {
    return opposite(h,*g);
  }
};

template <typename G>
struct Target {
  const G* g; 

  Target()
    : g(NULL)
  {}

  Target(const G& g)
    : g(&g)
  {}

  typedef typename boost::graph_traits<G>::vertex_descriptor result_type;
  typedef typename boost::graph_traits<G>::halfedge_descriptor argument_type;

  result_type operator()(argument_type h) const
  {
    return target(h,*g);
  }
};

template <typename G>
struct Source {
  const G* g; 

  Source()
    : g(NULL)
  {}

  Source(const G& g)
    : g(&g)
  {}

  typedef typename boost::graph_traits<G>::vertex_descriptor result_type;
  typedef typename boost::graph_traits<G>::halfedge_descriptor argument_type;

  result_type operator()(argument_type h) const
  {
    return source(h,*g);
  }
};

template <typename G>
struct Face {
  const G* g; 

  Face()
    : g(NULL)
  {}

  Face(const G& g)
    : g(&g)
  {}

  typedef typename boost::graph_traits<G>::face_descriptor result_type;
  typedef typename boost::graph_traits<G>::halfedge_descriptor argument_type;

  result_type operator()(argument_type h) const
  {
    return face(h,*g);
  }
};

  } // namespace internal


/**
 * \ingroup PkgBGLIterators
 * A bidirectional iterator with value type `boost::graph_traits<Graph>::%halfedge_descriptor` over all halfedges having the same vertex as source.
 * Let `h` be a halfedge of graph `g`. For a `Halfedge_around_source_iterator` `havi` with `h = *havi;` 
 * the following holds: Either `++havi` is the past the end iterator, or `next(opposite(h,g),g) == *++havi`. 
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalIterator`
 */
template <typename Graph>
class Halfedge_around_source_iterator {
  typedef Halfedge_around_source_iterator Self;
public:
#ifndef DOXYGEN_RUNNING
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor vertex_descriptor;
  typedef std::bidirectional_iterator_tag     iterator_category;
  typedef halfedge_descriptor                 value_type;
  typedef value_type*                         pointer;
  typedef const value_type&                   reference;
  typedef std::ptrdiff_t                      difference_type;

private:  
  halfedge_descriptor anchor, pos;
  const Graph* g;
  int      winding;
#endif 
  
public:
  Halfedge_around_source_iterator()
    : anchor(), pos(), g(0)
  {}

  Halfedge_around_source_iterator(halfedge_descriptor hd, const Graph& g, int n=0)
    : anchor(hd), pos(hd), g(&g), winding((hd==halfedge_descriptor())?1:n)
  {}

#ifndef DOXYGEN_RUNNING
  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Halfedge_around_source_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Halfedge_around_source_iterator::this_type_does_not_support_comparisons : 0;
  }

  bool operator==( const Self& i) const {
    CGAL_assertion( anchor == anchor);
    return  ( g == i.g) && ( pos == i.pos) && ( winding == i.winding);
  }
  
  bool operator!=( const Self& i) const {
    return !(*this == i);
  }

  bool operator== (void* ) const
  {
    return g == NULL;
  }

  reference operator*() const
  {
    return pos;
  }

  pointer operator->() const
  {
    return &pos;
  }

  Self& operator++() {
    pos = next(opposite(pos,*g),*g);
    if ( pos == anchor)
      ++winding;
    return *this;
  }
  Self  operator++(int) {
    Self tmp = *this;
    ++*this;
    return tmp;
  }
  Self& operator--() {
    if ( pos == anchor)
      --winding;
    pos = opposite(prev(pos,*g),*g);
    return *this;
  }
  Self  operator--(int) {
    Self tmp = *this;
    --*this;
    return tmp;
  }
#endif
};

/**
 * \ingroup PkgBGLIterators
 * A bidirectional iterator with value type `boost::graph_traits<Graph>::%halfedge_descriptor` over all halfedges having the same vertex as target.
 * Let `h` be a halfedge of graph `g`. For a `Halfedge_around_target_iterator` `havi` with `h = *havi;` 
 * the following holds: Either `++havi` is the past the end iterator, or `opposite(next(h,g),g) == *++havi`. 
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalIterator`
 */

template <typename Graph>
class Halfedge_around_target_iterator {
  typedef Halfedge_around_target_iterator Self;

public:
#ifndef DOXYGEN_RUNNING
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor vertex_descriptor;
  typedef std::bidirectional_iterator_tag     iterator_category;
  typedef halfedge_descriptor                 value_type;
  typedef value_type*                         pointer;
  typedef const value_type&                   reference;
  typedef std::ptrdiff_t                      difference_type;

private:  
  halfedge_descriptor anchor, pos;
  const Graph* g;
  int      winding;
#endif 
  
public:
  Halfedge_around_target_iterator()
    : anchor(), pos(), g(0)
  {}

  Halfedge_around_target_iterator(halfedge_descriptor hd, const Graph& g, int n=0)
    : anchor(hd), pos(hd), g(&g), winding((hd==halfedge_descriptor())?1:n)
  {}

#ifndef DOXYGEN_RUNNING
  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Halfedge_around_target_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Halfedge_around_target_iterator::this_type_does_not_support_comparisons : 0;
  }

  bool operator==( const Self& i) const {
    CGAL_assertion( anchor == anchor);
    return  ( g == i.g) && ( pos == i.pos) && ( winding == i.winding);
  }
  
  bool operator!=( const Self& i) const {
    return !(*this == i);
  }

  bool operator== (void* ) const
  {
    return g == NULL;
  }

  reference operator*() const
  {
    return pos;
  }

  pointer operator->() const
  {
    return &pos;
  }

  Self& operator++() {
    pos = opposite(next(pos,*g),*g);
    if ( pos == anchor)
      ++winding;
    return *this;
  }
  Self  operator++(int) {
    Self tmp = *this;
    ++*this;
    return tmp;
  }
  Self& operator--() {
    if ( pos == anchor)
      --winding;
    pos = prev(opposite(pos,*g),*g);
    return *this;
  }
  Self  operator--(int) {
    Self tmp = *this;
    --*this;
    return tmp;
  }
#endif
};


/**
 * \ingroup PkgBGLIterators
 * A bidirectional iterator  with value type `boost::graph_traits<Graph>::%halfedge_descriptor` over all halfedges incident to the same face.
 * Let `h` be a halfedge of graph `g`. For a `Halfedge_around_face_iterator` `hafi` with  `h = *hafi` 
 * the following holds: Either `++hafi` is the past the end iterator, or `next(h,g) == *++hafi`.
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalIterator`
 */

template <typename Graph>
class Halfedge_around_face_iterator {
#ifndef DOXYGEN_RUNNING 
  typedef Halfedge_around_face_iterator Self;

public:
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef std::bidirectional_iterator_tag      iterator_category;
  typedef halfedge_descriptor                 value_type;
  typedef value_type*                         pointer;
  typedef value_type&                         reference;
  typedef std::ptrdiff_t                      difference_type;
  
#endif
  
  Halfedge_around_face_iterator()
    : pos(), g(0)
  {}

  Halfedge_around_face_iterator(halfedge_descriptor hd, const Graph& g, int n=0)
    : anchor(hd), pos(hd), g(&g), winding((hd == halfedge_descriptor())?1:n)
  {}
#ifndef DOXYGEN_RUNNING
  reference         operator *  ( )       { return  pos; }
  const value_type& operator *  ( ) const { return  pos; }
  pointer           operator -> ( )       { return &pos; }
  const value_type* operator -> ( ) const { return &pos; }

  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Halfedge_around_face_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Halfedge_around_face_iterator::this_type_does_not_support_comparisons : 0;
  }

  bool operator==( const Self& i) const {
    CGAL_assertion( anchor == anchor);
    return  ( g == i.g) && ( pos == i.pos) && ( winding == i.winding);
  }

  bool operator!=( const Self& i) const {
    return !(*this == i);
  }

  Self& operator++() 
  {
    CGAL_assertion(g != NULL);
    pos = next(pos,*g); 
    if ( pos == anchor)
      ++winding;
    return *this;
  }

  Self operator++(int) 
  {
    CGAL_assertion(g != NULL);
    Self tmp = *this;
    ++*this;
    return tmp;
  }

  Self& operator--() 
  {
    CGAL_assertion(g != NULL); 
    if ( pos == anchor)
      --winding;
  
    pos = prev(pos,*g);
    return *this;
  }

  Self operator--(int) 
  {
    CGAL_assertion(g != NULL);
    Self tmp = *this;
    --*this;
    return tmp;
  }
#endif
private:
  halfedge_descriptor anchor, pos;
  const Graph* g;
  int      winding;
};


template <typename Graph>
class Halfedge_around_target_circulator;

/**
 * \ingroup PkgBGLIterators
 * A bidirectional circulator  with value type `boost::graph_traits<Graph>::%halfedge_descriptor` over all halfedges having the same vertex as source.
 * Let `h` be a halfedge of graph `g`. For a `Halfedge_around_source_circulator` `havc` with `h = *havc;` 
 * the following holds: `next(opposite(h,g),g) == *++havc`. 
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalCirculator`
 */
template <typename Graph>
class Halfedge_around_source_circulator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::OppositeHalfedge<Graph>, Halfedge_around_target_circulator<Graph> >
#endif
{
#ifndef DOXYGEN_RUNNING
  typedef boost::transform_iterator<internal::OppositeHalfedge<Graph>, Halfedge_around_target_circulator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
#endif

public:

#ifndef DOXYGEN_RUNNING
  typedef Bidirectional_circulator_tag iterator_category;
  typedef std::size_t size_type;
#endif

  Halfedge_around_source_circulator()
  {}

  Halfedge_around_source_circulator(halfedge_descriptor hd, const Graph& g)
    : Base(Halfedge_around_target_circulator<Graph>(hd,g), internal::OppositeHalfedge<Graph>(g))
  {}

  Halfedge_around_source_circulator(vertex_descriptor vd, const Graph& g)
    : Base(Halfedge_around_target_circulator<Graph>(halfedge(vd,g),g), internal::OppositeHalfedge<Graph>(g))
  {}
}; 


/**
 * \ingroup PkgBGLIterators
 * A bidirectional circulator  with value type `boost::graph_traits<Graph>::%face_descriptor` over all faces incident to the same vertex.
 * It circulates over the same halfedges as the `Halfedge_around_target_circulator`.
 *
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalCirculator`
 */

template <typename Graph>
class Face_around_target_circulator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Face<Graph>, Halfedge_around_target_circulator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Face<Graph>, Halfedge_around_target_circulator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:

  Face_around_target_circulator()
  {}

  Face_around_target_circulator(halfedge_descriptor hd, const Graph& g)
    : Base(Halfedge_around_target_circulator<Graph>(hd,g), internal::Face<Graph>(g))
  {}
#ifndef DOXYGEN_RUNNING
  typedef Bidirectional_circulator_tag iterator_category;
  typedef std::size_t size_type;

  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Face_around_target_circulator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Face_around_target_circulator::this_type_does_not_support_comparisons : 0;
  }

  bool operator== (void*) const
  {
    return this->base() == NULL;
  }
#endif

}; 


/**
 * \ingroup PkgBGLIterators
 * A bidirectional circulator  with value type `boost::graph_traits<Graph>::%halfedge_descriptor` over all halfedges having the same vertex as target.
 * Let `h` be a halfedge of graph `g`. For a `Halfedge_around_target_circulator` `havc` with `h = *havc;` 
 * the following holds: `opposite(next(h,g),g) == *++havc`. 
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalCirculator`
 */



template <typename Graph>
class Halfedge_around_target_circulator {
  typedef Halfedge_around_target_circulator Self;

public:
#ifndef DOXYGEN_RUNNING
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  typedef Bidirectional_circulator_tag        iterator_category;
  typedef halfedge_descriptor                 value_type;
  typedef value_type*                         pointer;
  typedef value_type&                         reference;
  typedef std::ptrdiff_t                      difference_type;
  typedef std::size_t                         size_type;
#endif 

  Halfedge_around_target_circulator()
    : g(0)
  {}

  Halfedge_around_target_circulator(halfedge_descriptor pos, const Graph& g)
    : pos(pos), g(&g)
  {}

  Halfedge_around_target_circulator(vertex_descriptor vd, const Graph& g)
    : pos(halfedge(vd,g)), g(&g)
  {}

#ifndef DOXYGEN_RUNNING
  reference         operator *  ( )       { return  pos; }
  const value_type& operator *  ( ) const { return  pos; }
  pointer           operator -> ( )       { return &pos; }
  const value_type* operator -> ( ) const { return &pos; }

  bool       operator == ( const Self& other) const { return  g == other.g && pos == other.pos; }
  bool       operator != ( const Self& other) const { return  g != other.g || pos != other.pos; }


  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Halfedge_around_target_circulator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (g == NULL)) ?
      &Halfedge_around_target_circulator::this_type_does_not_support_comparisons : 0;
  }


  bool operator== (void* ) const
  {
    return g == NULL;
  }

 
  Self& operator++() 
  {
    CGAL_assertion(g != NULL);
    pos = opposite(next(pos,*g),*g);
    return *this;
  }

  Self operator++(int) 
  {
    CGAL_assertion(g != NULL);
    Self tmp = *this;
    ++*this;
    return tmp;
  }

  Self& operator--() 
  {
    CGAL_assertion(g != NULL);
    pos = prev(opposite(pos,*g),*g);
    return *this;
  }

  Self operator--(int) 
  {
    CGAL_assertion(g != NULL);
    Self tmp = *this;
    --*this;
    return tmp;
  }
#endif

private:
  halfedge_descriptor pos;
  const Graph* g;
};


/**
 * \ingroup PkgBGLIterators
 * A bidirectional circulator  with value type `boost::graph_traits<Graph>::%halfedge_descriptor` over all halfedges incident to the same face.
 * Let `h` be a halfedge of graph `g`. For a `Halfedge_around_face_circulator` `hafc` with  `h = *hafc` 
 * the following holds:  `next(h,g) == *++hafc`.
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalCirculator`
 */

template <typename Graph>
class Halfedge_around_face_circulator {
  typedef Halfedge_around_face_circulator Self;

public:
#ifndef DOXYGEN_RUNNING
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef Bidirectional_circulator_tag        iterator_category;
  typedef halfedge_descriptor                 value_type;
  typedef value_type*                         pointer;
  typedef value_type&                         reference;
  typedef std::ptrdiff_t                      difference_type;
  typedef std::size_t                         size_type;
#endif 
  
  Halfedge_around_face_circulator()
    : pos(), g(0)
  {}

  Halfedge_around_face_circulator(halfedge_descriptor pos, const Graph& g)
    : pos(pos), g(&g)
  {}
#ifndef DOXYGEN_RUNNING
  reference         operator *  ( )       { return  pos; }
  const value_type& operator *  ( ) const { return  pos; }
  pointer           operator -> ( )       { return &pos; }
  const value_type* operator -> ( ) const { return &pos; }

  bool       operator == ( const Self& other) const { return  g == other.g && pos == other.pos; }
  bool       operator != ( const Self& other) const { return  g != other.g || pos != other.pos; }
 

  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Halfedge_around_face_circulator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Halfedge_around_face_circulator::this_type_does_not_support_comparisons : 0;
  }

  bool operator== (void* ) const
  {
    return g == NULL;
  }

  Self& operator++() 
  {
    CGAL_assertion(g != NULL);
    pos = next(pos,*g);
    return *this;
  }

  Self operator++(int) 
  {
    CGAL_assertion(g != NULL);
    Self tmp = *this;
    ++*this;
    return tmp;
  }

  Self& operator--() 
  {
    CGAL_assertion(g != NULL);
    pos = prev(pos,*g);
    return *this;
  }

  Self operator--(int) 
  {
    CGAL_assertion(g != NULL);
    Self tmp = *this;
    --*this;
    return tmp;
  }
#endif

private:
  halfedge_descriptor pos;
  const Graph* g;
};


/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all halfedges with vertex `source(h,g)` as source.
 */
template<typename Graph>
std::pair<Halfedge_around_source_iterator<Graph>,Halfedge_around_source_iterator<Graph> >
halfedges_around_source(typename boost::graph_traits<Graph>::halfedge_descriptor h, Graph& g)
{
  typedef Halfedge_around_source_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all halfedges with vertex `v` as source.
 */
template<typename Graph>
std::pair<Halfedge_around_source_iterator<Graph>,Halfedge_around_source_iterator<Graph> >
halfedges_around_source(typename boost::graph_traits<Graph>::vertex_descriptor v, Graph& g)
{
  return halfedges_around_source(opposite(halfedge(v,g),g),g);
}

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all halfedges with vertex `target(h,g)` as target. 
 */
template<typename Graph>
std::pair<Halfedge_around_target_iterator<Graph>,Halfedge_around_target_iterator<Graph> >
halfedges_around_target(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Halfedge_around_target_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all halfedges with vertex `v` as target. 
 */
template<typename Graph>
std::pair<Halfedge_around_target_iterator<Graph>,Halfedge_around_target_iterator<Graph> >
halfedges_around_target(typename boost::graph_traits<Graph>::vertex_descriptor v, Graph& g)
{
  return halfedges_around_target(halfedge(v,g),g);
}

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all halfedges incident to the same face as `h`. 
 */
template<typename Graph>
std::pair<Halfedge_around_face_iterator<Graph>,Halfedge_around_face_iterator<Graph> >
halfedges_around_face(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Halfedge_around_face_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}


template <typename Graph>
class Face_around_face_iterator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Face<Graph>, Halfedge_around_face_iterator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Face<Graph>, Halfedge_around_face_iterator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
#ifndef DOXYGEN_RUNNING
  typedef std::bidirectional_iterator_tag iterator_category;
#endif

  Face_around_face_iterator()
  {}

  Face_around_face_iterator(halfedge_descriptor h, const Graph& g, int n = 0)
    : Base(Halfedge_around_face_iterator<Graph>(h,g,(h==halfedge_descriptor())?1:n), internal::Face<Graph>(g))
  {}
}; 


/**
 * \ingroup PkgBGLIterators
 * A bidirectional circulator  with value type `boost::graph_traits<Graph>::%face_descriptor` over all faces adjacent to the same face.
 * It circulates over the same halfedges as the `Halfedge_around_face_circulator`.
 *
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalCirculator`
 */



template <typename Graph>
class Face_around_face_circulator
{};


template <typename Graph>
class Face_around_target_iterator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Face<Graph>, Halfedge_around_target_iterator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Face<Graph>, Halfedge_around_target_iterator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
#ifndef DOXYGEN_RUNNING
  typedef std::bidirectional_iterator_tag iterator_category;
#endif

  Face_around_target_iterator()
  {}

  Face_around_target_iterator(halfedge_descriptor h, const Graph& g, int n = 0)
    : Base(Halfedge_around_target_iterator<Graph>(h,g,(h==halfedge_descriptor())?1:n), internal::Face<Graph>(g))
  {}
}; 

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all faces around  vertex `target(h,g)`. 
 */
template<typename Graph>
std::pair<Face_around_target_iterator<Graph>,Face_around_target_iterator<Graph> >
faces_around_target(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Face_around_target_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all faces adjacent to the same face `face(h,g)`. 
 */
template<typename Graph>
std::pair<Face_around_face_iterator<Graph>,Face_around_face_iterator<Graph> >
faces_around_face(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Face_around_face_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}

template <typename Graph>
class Vertex_around_face_circulator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Target<Graph>, Halfedge_around_face_circulator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Target<Graph>, Halfedge_around_face_circulator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
#ifndef DOXYGEN_RUNNING
  typedef Bidirectional_circulator_tag iterator_category;
  typedef std::size_t size_type;
#endif

  Vertex_around_face_circulator()
  {}

  Vertex_around_face_circulator(halfedge_descriptor h, const Graph& g)
    : Base(Halfedge_around_face_circulator<Graph>(h,g), internal::Target<Graph>(g))
  {}

#ifndef DOXYGEN_RUNNING
  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Vertex_around_face_circulator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Vertex_around_face_circulator::this_type_does_not_support_comparisons : 0;
  }

  bool operator== (void*) const
  {
    return this->base()== NULL;
  }
#endif
}; 

template <typename Graph>
class Vertex_around_face_iterator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Target<Graph>, Halfedge_around_face_iterator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Target<Graph>, Halfedge_around_face_iterator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
#ifndef DOXYGEN_RUNNING
  typedef std::bidirectional_iterator_tag iterator_category;
#endif

  Vertex_around_face_iterator()
  {}

  Vertex_around_face_iterator(halfedge_descriptor h, const Graph& g, int n = 0)
    : Base(Halfedge_around_face_iterator<Graph>(h,g,(h==halfedge_descriptor())?1:n), internal::Target<Graph>(g))
  {}

#ifndef DOXYGEN_RUNNING
  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Vertex_around_face_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Vertex_around_face_iterator::this_type_does_not_support_comparisons : 0;
  }

  bool operator== (void*) const
  {
    return this->base()== NULL;
  }
#endif
}; 


/**
 * \ingroup PkgBGLIterators
 * A bidirectional circulator  with value type `boost::graph_traits<Graph>::%vertex_descriptor` over all vertices adjacent to the same vertex.
 * It circulates over the same halfedges as the `Halfedge_around_target_circulator`.
 *
 * \tparam Graph must be a model of the concept `HalfedgeGraph`
 * \cgalModels `BidirectionalCirculator`
 */

template <typename Graph>
class Vertex_around_target_circulator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Source<Graph>, Halfedge_around_target_circulator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Source<Graph>, Halfedge_around_target_circulator<Graph> > Base;

public:
#ifndef DOXYGEN_RUNNING
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;
  typedef Bidirectional_circulator_tag iterator_category;
  typedef std::size_t size_type;
#endif

  Vertex_around_target_circulator()
  {}

  Vertex_around_target_circulator(halfedge_descriptor h, const Graph& g)
    : Base(Halfedge_around_target_circulator<Graph>(h,g), internal::Source<Graph>(g))
  {}

#ifndef DOXYGEN_RUNNING  
  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Vertex_around_target_circulator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Vertex_around_target_circulator::this_type_does_not_support_comparisons : 0;
  }
#endif
}; 




template <typename Graph>
class Vertex_around_target_iterator
#ifndef DOXYGEN_RUNNING
  : public boost::transform_iterator<internal::Source<Graph>, Halfedge_around_target_iterator<Graph> >
#endif
{
  typedef boost::transform_iterator<internal::Source<Graph>, Halfedge_around_target_iterator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
  typedef std::bidirectional_iterator_tag iterator_category;

  Vertex_around_target_iterator()
  {}

  Vertex_around_target_iterator(halfedge_descriptor h, const Graph& g, int n = 0)
    : Base(Halfedge_around_target_iterator<Graph>(h,g,(h==halfedge_descriptor())?1:n), internal::Source<Graph>(g))
  {}

#ifndef DOXYGEN_RUNNING
  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Vertex_around_target_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Vertex_around_target_iterator::this_type_does_not_support_comparisons : 0;
  }
#endif
}; 


template <typename Graph>
std::pair<Vertex_around_target_iterator<Graph>, Vertex_around_target_iterator<Graph> >
adjacent_vertices(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Vertex_around_face_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}


template <typename Graph>
std::pair<Vertex_around_target_iterator<Graph>, Vertex_around_target_iterator<Graph> >
adjacent_vertices(typename boost::graph_traits<Graph>::vertex_descriptor v, const Graph& g)
{
  typedef Vertex_around_face_iterator<Graph> I;
  return std::make_pair(I(halfedge(v,g),g), I(halfedge(v,g),g,1));
}

/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all vertices adjacent to the vertex `target(h,g)`. 
 */
template <typename Graph>
std::pair<Vertex_around_target_iterator<Graph>, Vertex_around_target_iterator<Graph> >
vertices_around_target(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Vertex_around_target_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}

template <typename Graph>
std::pair<Vertex_around_target_iterator<Graph>, Vertex_around_target_iterator<Graph> >
vertices_around_target(typename boost::graph_traits<Graph>::vertex_descriptor v, const Graph& g)
{
  typedef Vertex_around_target_iterator<Graph> I;
  return std::make_pair(I(halfedge(v,g),g), I(halfedge(v,g),g,1));
}
/**  
 * \ingroup PkgBGLIterators
 * returns an iterator range over all vertices adjacent to the face `face(h,g)`. 
 */
template <typename Graph>
std::pair<Vertex_around_face_iterator<Graph>, Vertex_around_face_iterator<Graph> >
vertices_around_face(typename boost::graph_traits<Graph>::halfedge_descriptor h, const Graph& g)
{
  typedef Vertex_around_face_iterator<Graph> I;
  return std::make_pair(I(h,g), I(h,g,1));
}

template <typename Graph>
class Out_edge_iterator
  : public boost::transform_iterator<internal::OppositeEdge<Graph>, Halfedge_around_target_iterator<Graph> >
{
  typedef boost::transform_iterator<internal::OppositeEdge<Graph>, Halfedge_around_target_iterator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
  typedef std::bidirectional_iterator_tag iterator_category;

  Out_edge_iterator()
  {}

  Out_edge_iterator(halfedge_descriptor h, const Graph& g, int n = 0)
    : Base(Halfedge_around_target_iterator<Graph>(h,g,(h==halfedge_descriptor())?1:n), internal::OppositeEdge<Graph>(g))
  {} 


  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (Out_edge_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &Out_edge_iterator::this_type_does_not_support_comparisons : 0;
  }

}; 


template <typename Graph>
class In_edge_iterator
  : public boost::transform_iterator<internal::Edge<Graph>, Halfedge_around_target_iterator<Graph> >
{
  typedef boost::transform_iterator<internal::Edge<Graph>, Halfedge_around_target_iterator<Graph> > Base;
  typedef typename boost::graph_traits<Graph>::halfedge_descriptor halfedge_descriptor;

public:
  typedef std::bidirectional_iterator_tag iterator_category;

  In_edge_iterator()
  {}

  In_edge_iterator(halfedge_descriptor h, const Graph& g, int n = 0)
    : Base(Halfedge_around_target_iterator<Graph>(h,g,(h==halfedge_descriptor())?1:n), internal::Edge<Graph>(g))
  {}


  // design patter: "safe bool"
  // will be replaced by explicit operator bool with C++11
  typedef void (In_edge_iterator::*bool_type)() const;

  void this_type_does_not_support_comparisons() const {}

  operator bool_type() const
  {
    return (! (this->base() == NULL)) ?
      &In_edge_iterator::this_type_does_not_support_comparisons : 0;
  }

}; 



} // CGAL


#endif /* CGAL_BGL_ITERATORS_H */
