//-*-c++-*-
#ifndef Tulip_SUPERGRAPHIMPL_H
#define Tulip_SUPERGRAPHIMPL_H
#include <set>

#if (__GNUC__ < 3)
#include <hash_set>
#else
#include <ext/hash_set>
#endif

#include <vector>
#include "SuperGraphAbstract.h"
#include "IdManager.h"
#include "SimpleVector.h"

class Cluster;
class PropertyProxyContainer;
class SubGraph;
class SuperGraphView;
template<class C>class Iterator;
class IntProxy;
///Implementation of the graph support of the SuperGraph.
class SuperGraphImpl:public SuperGraphAbstract
{
  friend class xSGraphNodeIterator;
  friend class xSGraphEdgeIterator;
  friend class xInOutEdgesIterator;
  friend class xOutEdgesIterator;
  friend class xInEdgesIterator;
  friend class xInOutNodesIterator;

private :
  typedef SimpleVector<edge> EdgeContainer;
  typedef std::vector<EdgeContainer> Nodes;
  typedef std::vector<std::pair< node , node > > Edges;
  PropertyProxyContainer *_propertiesProxyContainer;
  Cluster *_clusterTree;
  SubGraph *_rootView;
  SuperGraph *_superGraph;
  IntProxy *outDegree;
  //mutable std::hash_map<edge,std::pair< node , node > > edges;
  //mutable std::hash_map<node,std::pair< std::vector<edge> , std::vector<edge> > > nodes;
  mutable Edges edges;
  mutable Nodes nodes;
  IdManager nodeIds;
  IdManager edgeIds;
  unsigned int nbNodes;
  unsigned int nbEdges;

  static void removeEdge(EdgeContainer &, const edge);
  void externRemove(const edge);
  void externRemove(const node);
public:
  SuperGraphImpl();
  ~SuperGraphImpl();
  
  //=========================================================================
  ///Return the propertyProxy container associated to the graph
  PropertyProxyContainer *getPropertyProxyContainer();
  ///Return the father of this graph.
  SuperGraph *getFather() const;
  ///Returnthe cluster tree assoicated to the SuperGraph
  Cluster *getClusterTree();
  ///
  SubGraph* getSubGraph();
  //===========================================================================
  ///Return a view of the SuperGraph
  SuperGraph* getView(SubGraph *subGraph);
  ///Add a view to this SuperGraph
  SubGraph *addView(const std::string & name,SelectionProxy *selectionProxy);
  ///Delete a view of this SuperGraph
  void delView(SubGraph *view);
  ///Delete a view and all its subview of this SuperGraph
  void delAllView(SubGraph *view);

  //==============================================================================
  /** Return true if the node is element of the graph*/
  bool isElement(const node );
  /** Return true if the edge is element of the graph*/
  bool isElement(const edge );
  ///Add a node to this SuperGraph
  node addNode();
  void addNode(const node);
  ///Add an edge to this SuperGraph
  edge addEdge(const node ,const node);
  void addEdge(const edge);
  /**Delete a node to this SuperGraph 
     Warning, the current implementation doesn't manage the updating of properties 
     for upper_subgraph in the case of Super Graph Implementation*/
  void delNode(const node);
  /**Delete an edge to this SuperGraph
     Warning, the current implementation doesn't manage the updating of properties 
     for upper_subgraph in the case of Super Graph Implementation*/
  void delEdge(const edge );
  ///Delete a node in all the SuperGraph
  void delAllNode(const node );
  ///Delete an edge in all the SuperGraph
  void delAllEdge(const edge );
  //==============================================================================
  ///
  Iterator<node>* getNodes() const;
  ///
  Iterator<node>* getInNodes(const node )const;
  ///
  Iterator<node>* getOutNodes(const node )const;
  ///
  Iterator<node>* getInOutNodes(const node )const;
  ///
  Iterator<edge>* getEdges()const;
  ///
  Iterator<edge>* getInEdges(const node )const;
  ///
  Iterator<edge>* getOutEdges(const node )const;
  ///
  Iterator<edge>* getInOutEdges(const node )const;
  //================================================================================
  ///Return the degree of a node of this SuperGraph
  int deg(const node ) const;
  ///Return the in-degree of a node of this SuperGraph
  int indeg(const node) const;
  ///Return the out-degree of a node of this SuperGraph
  int outdeg(const node) const;
  //================================================================================
  // Functions for the acces to the edge informations
  //================================================================================
  ///Return the source of the edge.
  virtual node source(const edge) const;
  ///Return the target of the edge.
  virtual node target(const edge) const;
  /**
     Reverse edge direction, the source becomes the target, and the target
     becomes the source. Warning !! the edges are shared thus edge direction will be changed
     in all sub-graphs.
  */
  virtual void reverse(const edge);
  //================================================================================
  ///Return the number of nodes of this SuperGraph
  int numberOfEdges()const;
  ///Return the number of edges of this SuperGraph
  int numberOfNodes()const;
  //================================================================================
};

#endif
