// -*-mode: c++; -*-

template<typename G>
class TrivGraphWrapper
{
  G *graph;
  
public:
  typedef G BaseGraph;

  typedef typename G::EdgeIt EdgeIt;
  
  typedef typename G::InEdgeIt InEdgeIt;
  typedef typename G::OutEdgeIt OutEdgeIt;
  typedef typename G::SymEdgeIt SymEdgeIt;
  typedef typename G::EachEdgeIt EachEdgeIt;

  typedef typename G::NodeIt NodeIt;
    
  template<typename I> I &getFirst(I &i); { return graph->getFirst(i); }
  template<typename I,typename P> I &getFirst(I &i,const P &p);
  { return graph->getFirst(i,p); }
  template<typename I> I next(const I i); { return graph->goNext(i); }
  template<typename I> I &goNext(I &i); { return graph->goNext(i); }

  NodeIt head(const EdgeIt &e);
  { return graph->head(e); }
  NodeIt tail(const EdgeIt &e);
  { return graph->tail(e); }
  
  template<typename I> NodeIt aNode(const I e);
  { return graph->aNode(e); }
  template<typename I> NodeIt bNode(const I e);
  { return graph->bNode(e); }
  
  template<typename I> bool valid(const I i);
  { return graph->valid(i); }
  
  template<typename I> void setInvalid(const I &i);
  { return graph->setInvalid(i); }
  
  NodeIt addNode(); { return graph->addNode(); }
  EdgeIt addEdge(const NodeIt from,const NodeIt to);
  { return graph->addEdge(ftom,to); }
  
  template<I> void delete(I i); { graph->delete(i); }
  
  void clean();  { graph->clean(); }
  
  template<class T> class NodeMap : public typename G::NodeMap<T>;
  template<class T> class EdgeMap : public typename G::EdgeMap<T>;
  
  void SetG(G &g) {graph = &g;}
  
  TrivGraphWrapper() {graph = NULL;}
  TrivGraphWrapper(G &g) {graph = &g;}
};

template<typename G>
class RevGraphWrapper
{
  G *graph;
  
public:
  typedef G BaseGraph;

  typedef typename G::EdgeIt EdgeIt;
  
  typedef typename G::InEdgeIt OutEdgeIt;
  typedef typename G::OutEdgeIt InEdgeIt;
  typedef typename G::SymEdgeIt SymEdgeIt;
  typedef typename G::EachEdgeIt EachEdgeIt;

  typedef typename G::NodeIt NodeIt;
    
  template<typename I> I &getFirst(I &i); { return graph->getFirst(i); }
  template<typename I,typename P> I &getFirst(I &i,const P &p);
  { return graph->getFirst(i,p); }
  template<typename I> I next(const I i); { return graph->goNext(i); }
  template<typename I> I &goNext(I &i); { return graph->goNext(i); }

  NodeIt head(const EdgeIt &e);
  { return graph->tail(e); }
  NodeIt tail(const EdgeIt &e);
  { return graph->head(e); }
  
  template<typename I> NodeIt aNode(const I e);
  { return graph->aNode(e); }
  template<typename I> NodeIt bNode(const I e);
  { return graph->bNode(e); }
  
  template<typename I> bool valid(const I i);
  { return graph->valid(i); }
  
  template<typename I> void setInvalid(const I &i);
  { return graph->setInvalid(i); }
  
  NodeIt addNode(); { return graph->addNode(); }
  EdgeIt addEdge(const NodeIt from,const NodeIt to);
  { return graph->addEdge(to,from); }
  
  template<I> void delete(I i); { graph->delete(i); }
  
  void clean();  { graph->clean(); }
  
  template<class T> class NodeMap : public typename G::NodeMap<T>;
  template<class T> class EdgeMap : public typename G::EdgeMap<T>;
  
  void SetG(G &g) {graph = &g;}
  
  RevGraphWrapper() {graph = NULL;}
  RevGraphWrapper(G &g) {graph = &g;}
};

template<typename G>
class SymGraphWrapper
{
  G *graph;
  
public:
  typedef G BaseGraph;

  typedef typename G::EdgeIt EdgeIt;
  
  typedef typename G::InEdgeIt SymEdgeIt;
  typedef typename G::OutEdgeIt SymEdgeIt;
  typedef typename G::SymEdgeIt SymEdgeIt;
  typedef typename G::EachEdgeIt EachEdgeIt;

  typedef typename G::NodeIt NodeIt;
    
  template<typename I> I &getFirst(I &i); { return graph->getFirst(i); }
  template<typename I,typename P> I &getFirst(I &i,const P &p);
  { return graph->getFirst(i,p); }
  template<typename I> I next(const I i); { return graph->goNext(i); }
  template<typename I> I &goNext(I &i); { return graph->goNext(i); }

  NodeIt head(const EdgeIt &e);
  { return graph->head(e); }
  NodeIt tail(const EdgeIt &e);
  { return graph->tail(e); }
  
  template<typename I> NodeIt aNode(const I e);
  { return graph->aNode(e); }
  template<typename I> NodeIt bNode(const I e);
  { return graph->bNode(e); }
  
  template<typename I> bool valid(const I i);
  { return graph->valid(i); }
  
  template<typename I> void setInvalid(const I &i);
  { return graph->setInvalid(i); }
  
  NodeIt addNode(); { return graph->addNode(); }
  EdgeIt addEdge(const NodeIt from,const NodeIt to);
  { return graph->addEdge(to,from); }
  
  template<I> void delete(I i); { graph->delete(i); }
  
  void clean();  { graph->clean(); }
  
  template<class T> class NodeMap : public typename G::NodeMap<T>;
  template<class T> class EdgeMap : public typename G::EdgeMap<T>;
  
  void SetG(G &g) {graph = &g;}
  
  RevGraphWrapper() {graph = NULL;}
  RevGraphWrapper(G &g) {graph = &g;}
};


// FIXME: comparison should be made better!!!
template<typename G, typename lomap, typename fmap, typename himap>
class ResGraphWrapper
{
  G *graph;
  
public:
  typedef G BaseGraph;

  typedef typename G::EdgeIt EdgeIt;
  
  class InEdgeIt 
  {
  public:
    G::NodeIt n;
    G::InEdgeIt i;   
    G::OutEdgeIt o;
  }
  class OutEdgeIt 
  {
  public:
    G::NodeIt n;
    G::InEdgeIt i;   
    G::OutEdgeIt o;
  }
  typedef typename G::SymEdgeIt SymEdgeIt;
  typedef typename G::EachEdgeIt EachEdgeIt;

  typedef typename G::NodeIt NodeIt;
    
  NodeIt &getFirst(NodeIt &n); { return graph->getFirst(n); }

  // EachEdge and SymEdge  is missing!!!!
  // EdgeIt <-> In/OutEdgeIt conversion is missing!!!!

  InEdgeIt &getFirst(InEdgeIt &e,const NodeIt &n)
  {
    e.n=n;
    graph->getFirst(e.i,n);
    while(graph->valid(e.i) && fmap.get(e.i)>=himap.get(e.i))
      graph->goNext(e.i);
    if(!graph->valid(e.i)) {
      graph->getFirst(e.o,n);
      while(graph->valid(e.o) && fmap.get(e.o)<=lomap.get(e.o))
	graph->goNext(e.o);
    }
    return e;
  }
  InEdgeIt &goNext(InEdgeIt &e)
  {
    if(graph->valid(e.i)) {
      while(graph->valid(e.i) && fmap.get(e.i)>=himap.get(e.i))
	graph->goNext(e.i);
      if(graph->valid(e.i)) return e;
      else graph->getFirst(e.o,e.n);
    }
    else {
      while(graph->valid(e.o) && fmap.get(e.o)<=lomap.get(e.o))
	graph->goNext(e.o);
      return e;
    }
  }
  InEdgeIt Next(const InEdgeIt &e) {InEdgeIt t(e); return goNext(t);}
  bool valid(const InEdgeIt e) { return graph->valid(e.i)||graph->valid(e.o);}

  OutEdgeIt &getFirst(OutEdgeIt &e,const NodeIt &n)
  {
    e.n=n;
    graph->getFirst(e.o,n);
    while(graph->valid(e.o) && fmap.get(e.o)>=himap.get(e.o))
      graph->goNext(e.o);
    if(!graph->valid(e.o)) {
      graph->getFirst(e.i,n);
      while(graph->valid(e.i) && fmap.get(e.i)<=lomap.get(e.i))
	graph->goNext(e.i);
    }
    return e;
  }
  OutEdgeIt &goNext(OutEdgeIt &e)
  {
    if(graph->valid(e.o)) {
      while(graph->valid(e.o) && fmap.get(e.o)>=himap.get(e.o))
	graph->goNext(e.o);
      if(graph->valid(e.o)) return e;
      else graph->getFirst(e.i,e.n);
    }
    else {
      while(graph->valid(e.i) && fmap.get(e.i)<=lomap.get(e.i))
	graph->goNext(e.i);
      return e;
    }
  }
  OutEdgeIt Next(const OutEdgeIt &e) {OutEdgeIt t(e); return goNext(t);}
  bool valid(const OutEdgeIt e) { return graph->valid(e.o)||graph->valid(e.i);}

  template<typename I> I &goNext(I &i); { return graph->goNext(i); }
  template<typename I> I next(const I i); { return graph->goNext(i); }

  NodeIt head(const EdgeIt &e);
  { return graph->head(e); }
  NodeIt tail(const EdgeIt &e);
  { return graph->tail(e); }
  
  template<typename I> NodeIt aNode(const I e);
  { return graph->aNode(e); }
  template<typename I> NodeIt bNode(const I e);
  { return graph->bNode(e); }
  
  template<typename I> bool valid(const I i);
  { return graph->valid(i); }
  
  template<typename I> void setInvalid(const I &i);
  { return graph->setInvalid(i); }
  
  NodeIt addNode(); { return graph->addNode(); }
  EdgeIt addEdge(const NodeIt from,const NodeIt to);
  { return graph->addEdge(to,from); }
  
  template<I> void delete(I i); { graph->delete(i); }
  
  void clean();  { graph->clean(); }
  
  template<class T> class NodeMap : public typename G::NodeMap<T>;
  template<class T> class EdgeMap : public typename G::EdgeMap<T>;
  
  void SetG(G &g) {graph = &g;}
  
  RevGraphWrapper() {graph = NULL;}
  RevGraphWrapper(G &g) {graph = &g;}
};



//   NodeIt &getFirst(NodeIt &n) { return graph->getFirst(n); }
//   InEdgeIt &getFirst(InEdgeIt &e,const NodeIt &n);
//   { return graph->getFirst(e,n); }
//   OutEdgeIt &getFirst(OutEdgeIt &e,const NodeIt &n);
//   { return graph->getFirst(e,n); }
//   SymEdgeIt &getFirst(SymEdgeIt &e,const NodeIt &n);
//   { return graph->getFirst(e,n); }
//   EachEdgeIt &getFirst(EachEdgeIt &e);
//   { return graph->getFirst(e); }
   
//   NodeIt next(const NodeIt &n);
//   { return graph->next(n); }
//   InEdgeIt next(const InEdgeIt &e);
//   { return graph->next(e); }
//   OutEdgeIt next(const OutEdgeIt &e);
//   { return graph->next(e); }
//   SymEdgeIt next(const SymEdgeIt &e);
//   { return graph->next(e); }
//   EachEdgeIt next(const EachEdgeIt &e);
//   { return graph->next(e); }
 
//   NodeIt &goNext(NodeIt &n);
//   { return graph->goNext(n); }
//   InEdgeIt &goNext(InEdgeIt &e);
//   { return graph->goNext(e); }
//   OutEdgeIt &goNext(OutEdgeIt &e);
//   { return graph->goNext(e); }
//   SymEdgeIt &goNext(SymEdgeIt &e);
//   { return graph->goNext(e); }
//   EachEdgeIt &goNext(EachEdgeIt &e);
//   { return graph->goNext(e); }
 
