#ifndef DUNE_ALU2DGRID_ITERATOR_HH
#define DUNE_ALU2DGRID_ITERATOR_HH

// System includes
#include <stack>
#include <utility>

// Dune includes
#include <dune/grid/common/grid.hh>
#include <dune/grid/alugrid/common/intersectioniteratorwrapper.hh>

// Local includes 
#include "entity.hh"

namespace Dune {
  // Forward declarations
  template<int cd, int dim, class GridImp> 
  class ALU2dGridEntity;
  template<int cd, PartitionIteratorType pitype, class GridImp >
  class ALU2dGridLevelIterator;
  template<int cd, class GridImp > 
  class ALU2dGridEntityPointer;
  template<int mydim, int coorddim, class GridImp>
  class ALU2dGridGeometry;
  template<class GridImp> 
  class ALU2dGridHierarchicIterator;
  template<class GridImp>
  class ALU2dGridIntersectionBase;
  template<class GridImp>
  class ALU2dGridLeafIntersectionIterator;
  template<class GridImp>
  class ALU2dGridLevelIntersectionIterator;
  template<int codim, PartitionIteratorType pitype, class GridImp>
  class ALU2dGridLeafIterator;
  template< int dim, int dimworld, ALU2DSPACE ElementType eltype >
  class ALU2dGrid;
  
 
//********************************************************************
//  --ALU2dGridLeafIterator
//  --LeafIterator   
//  --for codim = 0,2
//
//********************************************************************

template<int cdim, PartitionIteratorType pitype, class GridImp>
class ALU2dGridLeafIterator
: public ALU2dGridEntityPointer<cdim,GridImp>
  // public LeafIteratorDefaultImplementation<cdim, pitype, GridImp, ALU2dGridLeafIterator> 
{
  static const int dim = GridImp::dimension;
  static const int dimworld  = GridImp::dimensionworld;
  static const ALU2DSPACE ElementType eltype = GridImp::elementType;
  static const int codim = cdim;

  friend class ALU2dGridEntity<0,dimworld,GridImp>;
  friend class ALU2dGridEntity<1,dimworld,GridImp>;
  friend class ALU2dGridEntity<dim,dimworld,GridImp>;  
  friend class ALU2dGrid< dim, dimworld, eltype >;
    
  typedef ALU2dGridEntityPointer<cdim,GridImp> EntityPointerType;  
  typedef ALU2dGridEntity<cdim,dim,GridImp> EntityImp;      

  typedef ALU2dGridLeafIterator<cdim, pitype, GridImp> ThisType;
 
  typedef typename GridImp :: ALU2dGridLeafMarkerVectorType LeafMarkerVectorType;

  // default impl for elements 
  template <class ElementImp, class MarkerVectorImp, int codim> 
  struct GetLevel
  {
    // return level of element 
    static int level(const ElementImp & elem, const MarkerVectorImp& marker)
    {
      return elem.level();
    }
  };
 
  // specialization for vertices 
  template <class ElementImp, class MarkerVectorImp> 
  struct GetLevel<ElementImp,MarkerVectorImp,2>
  {
    // return level of leaf vertex 
    static int level(const ElementImp & elem, const MarkerVectorImp& marker)
    {
      return marker.levelOfVertex(elem.getIndex()); 
    }
  };
 
 public:
  typedef typename GridImp :: GridObjectFactoryType  FactoryType;

  //! type of entity we iterate (interface)  
  typedef typename GridImp::template Codim<cdim>::Entity Entity;
  typedef typename Dune::ALU2dImplTraits< dimworld, eltype >::template Codim<cdim>::InterfaceType ElementType;  

  //! Constructor called by LeafIterator
  ALU2dGridLeafIterator(const FactoryType& factory, bool end);
  
  //! copy Constructor
  ALU2dGridLeafIterator(const ThisType & org);

  //! prefix increment
  void increment ();

  //! assigment of iterator 
  ThisType & operator = (const ThisType & org);

private:
  //! true if iterator is end iterator
  bool endIter_;
  //! actual level
  int level_;    
  ElementType * elem_;   
  typedef ALU2DSPACE Listwalkptr< ElementType > IteratorType;
  // Listwalkptr, behaves like a proxy for Leafwalk and Levelwalk Ptrs
  IteratorType iter_;
  
  // for the codim 2 case
  LeafMarkerVectorType & marker_;
};  // end ALU2dGridLeafIterator


//********************************************************************
//  --ALU2dGridLeafIterator
//  --LeafIterator   
//  --specialized for codim = 1
//
//********************************************************************

template<PartitionIteratorType pitype, class GridImp>
class ALU2dGridLeafIterator<1,pitype,GridImp>
: public ALU2dGridEntityPointer<1,GridImp>
  // public LeafIteratorDefaultImplementation<1, pitype, GridImp, ALU2dGridLeafIterator> 
{
  static const int dim = GridImp::dimension;
  static const int dimworld  = GridImp::dimensionworld;
  static const ALU2DSPACE ElementType eltype = GridImp::elementType;
  static const int codim = 1;

  friend class ALU2dGridEntity<0,dimworld,GridImp>;
  friend class ALU2dGridEntity<1,dimworld,GridImp>;
  friend class ALU2dGridEntity<dim,dimworld,GridImp>;  
  friend class ALU2dGrid< dim, dimworld, eltype >;
    
  typedef ALU2dGridEntityPointer<1,GridImp> EntityPointerType;  
  typedef ALU2dGridEntity<1,dim,GridImp> EntityImp;      

  typedef ALU2dGridLeafIterator<1, pitype, GridImp> ThisType;

  typedef typename GridImp :: ALU2dGridLeafMarkerVectorType LeafMarkerVectorType;
 
 public:
  typedef typename GridImp :: GridObjectFactoryType  FactoryType;

  //! type of entity we iterate (interface)  
  typedef typename GridImp::template Codim<1>::Entity Entity;
  typedef typename Dune::ALU2dImplTraits< dimworld, eltype >::template Codim<1>::InterfaceType ElementType;  

  //! Constructor called by LeafIterator
  ALU2dGridLeafIterator(const FactoryType& factory, bool end);
  
  //! copy Constructor
  ALU2dGridLeafIterator(const ThisType & org);

  //! prefix increment
  void increment ();

  //! assigment of iterator 
  ThisType & operator = (const ThisType & org);

private:  
  int goNextElement();

  //! true if iterator is end iterator
  bool endIter_;
  //! actual level
  int level_; 
  //! information for edges
  int face_;  
    
  //! pointer to element 
  ElementType * elem_;
   
  typedef ALU2DSPACE Listwalkptr< ElementType > IteratorType;

  // Listwalkptr, behaves like a proxy for Leafwalk and Levelwalk Ptrs
  IteratorType iter_;

  // for the codim 1 case
  LeafMarkerVectorType & marker_;

};  // end ALU2dGridLeafIterator

//**********************************************************************
//
// --ALU2dGridLevelIterator
// --LevelIterator, specialized for cd=0
//**********************************************************************

template<PartitionIteratorType pitype, class GridImp>
class ALU2dGridLevelIterator<0, pitype, GridImp>
: public ALU2dGridEntityPointer<0,GridImp>
  // public LevelIteratorDefaultImplementation <0, pitype, GridImp, ALU2dGridLevelIterator>
{
  static const int dim = GridImp::dimension;
  static const int dimworld  = GridImp::dimensionworld;
  static const ALU2DSPACE ElementType eltype = GridImp::elementType;
  static const int codim = 0;
  
  friend class ALU2dGridEntity<dim,dimworld,GridImp>;
  friend class ALU2dGridEntity<1,dimworld,GridImp>;
  friend class ALU2dGridEntity<0,dimworld,GridImp>;
  friend class ALU2dGrid< dim, dimworld, eltype >;
  
  typedef ALU2dGridEntityPointer<codim,GridImp> EntityPointerType; 
  typedef ALU2dGridEntity<codim,dim,GridImp> EntityImp;      
  
  typedef typename ALU2dImplTraits< dimworld, eltype >::HElementType HElementType;
  typedef ALU2dGridLevelIterator<0,pitype,GridImp> ThisType; 
  
public:  
  typedef typename GridImp :: GridObjectFactoryType  FactoryType;

  typedef typename GridImp::template Codim<codim>::Entity Entity;
 
  //! Constructor 
  ALU2dGridLevelIterator(const FactoryType& factory, int level, bool end);  
    
  //! copy constructor
  ALU2dGridLevelIterator(const ThisType & org);      
  
  //! prefix increment
  void increment ();

  //! do not allow assigment
  ThisType & operator = (const ThisType & org);

private:
  //! true if iterator is end iterator
  bool endIter_;
  //! actual level
  int level_; 
  
  //! pointer to element 
  HElementType * item_;  
  
  //! type of entity we iterate (interface)   
  typedef typename Dune::ALU2dImplTraits< dimworld, eltype  >::template Codim<0>::InterfaceType ElementType;   
  typedef ALU2DSPACE Listwalkptr< ElementType > IteratorType;
  IteratorType iter_;  
  
}; 

//**********************************************************************
//
// --ALU2dGridLevelIterator
// --LevelIterator, specialized for cd=1
//**********************************************************************

template<PartitionIteratorType pitype, class GridImp>
class ALU2dGridLevelIterator<1, pitype, GridImp>
: public ALU2dGridEntityPointer<1,GridImp> 
  // public LevelIteratorDefaultImplementation <1, pitype, GridImp, ALU2dGridLevelIterator>
{
  static const int dim = GridImp::dimension;
  static const int dimworld  = GridImp::dimensionworld;
  static const ALU2DSPACE ElementType eltype = GridImp::elementType;
  static const int codim = 1;
  
  friend class ALU2dGridEntity<dim,dimworld,GridImp>;
  friend class ALU2dGridEntity<1,dimworld,GridImp>;
  friend class ALU2dGridEntity<0,dimworld,GridImp>;
  friend class ALU2dGrid< dim, dimworld, eltype >;
  
  typedef ALU2dGridEntityPointer<codim,GridImp> EntityPointerType; 
  typedef ALU2dGridEntity<codim,dim,GridImp> EntityImp;      
  
  typedef typename ALU2dImplTraits< dimworld, eltype >::HElementType HElementType;
  
  typedef ALU2dGridLevelIterator<1,pitype,GridImp> ThisType; 
public:  
  typedef typename GridImp :: GridObjectFactoryType  FactoryType;

  typedef typename GridImp::template Codim<codim>::Entity Entity;
 
  //! Constructor 
  ALU2dGridLevelIterator(const FactoryType& factroy, int level, bool end);  
    
  //! copy constructor
  ALU2dGridLevelIterator(const ThisType & org);      
  
  ~ALU2dGridLevelIterator();      
  
  //! prefix increment
  void increment ();

  //! assigment of iterator 
  ThisType & operator = (const ThisType & org);

private:
  //! true if iterator is end iterator
  bool endIter_;
  //! actual level
  int level_; 
  //! information for edges
  int myFace_;  

  // current item 
  HElementType * item_;  
  //! type of entity we iterate (interface)   
  typedef typename Dune::ALU2dImplTraits< dimworld, eltype >::template Codim<1>::InterfaceType ElementType;  
  ElementType * elem_;
  // Listwalkptr is a proxy for iterator pointers 
  typedef ALU2DSPACE Listwalkptr< ElementType > IteratorType;

  IteratorType iter_;  
  
  ALU2dGridMarkerVector * marker_;

  ALU2dGridMarkerVector & marker() 
  { 
    assert( marker_ );
    return *marker_; 
  }
}; 

//**********************************************************************
//
// --ALU2dGridLevelIterator
// --LevelIterator, specialized for cd=2
//**********************************************************************

template<PartitionIteratorType pitype, class GridImp>
class ALU2dGridLevelIterator<2, pitype, GridImp>
: public ALU2dGridEntityPointer<2,GridImp>
  // public LevelIteratorDefaultImplementation <2, pitype, GridImp, ALU2dGridLevelIterator>
{
  static const int dim = GridImp::dimension;
  static const int dimworld  = GridImp::dimensionworld;
  static const ALU2DSPACE ElementType eltype = GridImp::elementType;
  static const int codim = 2;
  
  friend class ALU2dGridEntity<dim,dimworld,GridImp>;
  friend class ALU2dGridEntity<1,dimworld,GridImp>;
  friend class ALU2dGridEntity<0,dimworld,GridImp>;
  friend class ALU2dGrid< dim, dimworld, eltype >;
  
  typedef ALU2dGridEntityPointer<codim,GridImp> EntityPointerType; 
  typedef ALU2dGridEntity<codim,dim,GridImp> EntityImp;      
  
  typedef typename ALU2dImplTraits< dimworld, eltype >::HElementType HElementType ;
  typedef ALU2dGridLevelIterator<2,pitype,GridImp> ThisType; 
  
public:  
  typedef typename GridImp :: GridObjectFactoryType  FactoryType;

  typedef typename GridImp::template Codim<codim>::Entity Entity;
 
  //! Constructor 
  ALU2dGridLevelIterator(const FactoryType& factory, int level, bool end);  
    
  //! copy constructor
  ALU2dGridLevelIterator(const ThisType & org);      
  
  ~ALU2dGridLevelIterator();      
  
  //! prefix increment
  void increment ();

  //! assigment of iterator 
  ThisType & operator = (const ThisType & org);

private:
  //! true if iterator is end iterator
  bool endIter_;
  //! actual level
  int level_; 
  //! information for edges
  int myFace_;  
  //! true if iterator is already a copy
    
  //! type of entity we iterate (interface)   
  typedef typename Dune::ALU2dImplTraits< dimworld, eltype >::template Codim<0>::InterfaceType ElementType;
  typedef typename Dune::ALU2dImplTraits< dimworld, eltype >::template Codim<2>::InterfaceType VertexType;

  HElementType * item_;
  VertexType * vertex_;
  
 
  typedef ALU2DSPACE Listwalkptr< ElementType > IteratorType;
  IteratorType iter_;  
  
  // marker vector to tell on which element vertex is visited 
  ALU2dGridMarkerVector * marker_;
  ALU2dGridMarkerVector & marker() 
  { 
    assert( marker_ );
    return *marker_; 
  }
}; 

//***************************************************************
//
// - HierarchicIteraror
// --HierarchicIterator
//***************************************************************

//! Hierarchic Iterator of ALU2dGrid 
template<class GridImp>
class ALU2dGridHierarchicIterator
: public ALU2dGridEntityPointer<0,GridImp>
  // public HierarchicIteratorDefaultImplementation <GridImp,ALU2dGridHierarchicIterator>
{
  typedef ALU2dGridHierarchicIterator<GridImp> ThisType;

  static const int dim = GridImp::dimension;
  static const int dimworld  = GridImp::dimensionworld;
  static const ALU2DSPACE ElementType eltype = GridImp::elementType;
  static const int codim = 2;
  
  typedef typename ALU2dImplTraits< dimworld, eltype >::HElementType HElementType ;
  
public:
  typedef typename GridImp :: GridObjectFactoryType  FactoryType;

  //! type of entities we iterate 
  typedef typename GridImp::template Codim<0>::Entity Entity;
  //! type of coordinates, i.e. double 
  typedef typename GridImp::ctype ctype;
  //! tpye of entity implementation 
  typedef ALU2dGridEntity<0,dim,GridImp> EntityImp;

  //! the normal Constructor
  ALU2dGridHierarchicIterator(const FactoryType& factory, 
                              const HElementType & elem, int maxlevel, bool end=false);
  
  //! the normal Constructor
  ALU2dGridHierarchicIterator(const ALU2dGridHierarchicIterator<GridImp> &org);
    
  //! increment, go to next entity
  void increment();
  
  //! the assignment operator
  ThisType & operator = (const ALU2dGridHierarchicIterator<GridImp> &org)
  {
    ALU2dGridEntityPointer<0,GridImp> :: operator = (org);
    elem_ = org.elem_;
    maxlevel_= org.maxlevel_;
    endIter_ = org.endIter_;
    return *this;
  }
  
private:

  //! go to next valid element
  HElementType * goNextElement (HElementType * oldEl);
    
  //! element from where we started
  const HElementType * elem_;
     
  //! maximal level to go down
  int maxlevel_;
  //! true if iterator is end iterator
  bool endIter_;
};  // end ALU2dHierarchicIterator 

} // end namespace Dune

#include "iterator_imp.cc"

#endif // #ifndef DUNE_ALU2DGRID_ITERATOR_HH
