//-*-c++-*-
/**
 Author: David Auber
 Email : auber@labri.fr
 Last modification : 20/08/2001
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by  
 the Free Software Foundation; either version 2 of the License, or     
 (at your option) any later version.
*/
#ifndef Tulip_SUPERGRAPH_H
#define Tulip_SUPERGRAPH_H

#include <iostream>
#include <string>

#if (__GNUC__ < 3)
#include <hash_map>
#else
#include <ext/hash_map>
#endif
#include <climits>
#include "tulipconf.h"
#include "Reflect.h"

class Cluster;
class PropertyProxyContainer;
class SubGraph;
template<class C>class Iterator;
class SelectionProxy;

namespace Tulip {
  enum AtomType {NODE=0, EDGE};
}

struct node{ 
  unsigned int id;
  node():id(UINT_MAX){}
  explicit node(unsigned int j):id(j){}
  bool operator!=(const node n) const {return id!=n.id;}
  bool operator==(const node n) const {return id==n.id;}
};

struct edge{ 
  unsigned int id;
  edge():id(UINT_MAX){}
  explicit edge(unsigned int j):id(j){}
  bool operator==(const edge e) const{return id==e.id;}
  bool operator!=(const edge e) const{return id!=e.id;}
};

namespace STL_EXT_NS {
template <> struct hash<node>{size_t operator()(const node n) const {return n.id;}};
template <> struct hash<edge>{size_t operator()(const edge e) const {return e.id;}};
}
namespace std {
template <> struct equal_to<node>{size_t operator()(const node n,const node n2) const {return n.id==n2.id;}};
template <> struct equal_to<edge>{size_t operator()(const edge e,const edge e2) const {return e.id==e2.id;}};
template <> struct less<node>{size_t operator()(const node n,const node n2) const {return n.id<n2.id;}};
template <> struct less<edge>{size_t operator()(const edge e,const edge e2) const {return e.id<e2.id;}};
}


///SuperGraph class is the interface a Graph in the Tulip Library
class SuperGraph
{
private:
  static int maxId;
  int id;

public:  
  //=========================================================================
  SuperGraph(){id=maxId++;}
  //=========================================================================  
  virtual ~SuperGraph(){};
  //=========================================================================  
  ///Return the graph's id, this id is unique.
  int getId() const {return id;}

  //=========================================================================  
  //Accessor to the super graph.
  //=========================================================================
  /**
   *  Return a pointer on the porperty proxy container associated to the 
   *  supergraph.
   */
  virtual  PropertyProxyContainer *getPropertyProxyContainer()=0;
  /**
   * Return the Cluster associated to the supergraph.
   */
  virtual Cluster *getClusterTree()=0;
  //===========================================================================
  // View manipulations
  //===========================================================================
  ///return a pointer to a view which represents the subGraph given in parameter
  virtual SuperGraph *getView(SubGraph *subGraph)=0;
  ///Return the subGraph that this superGraph is representing.
  virtual SubGraph *getSubGraph()=0;
  /**
   * Create a new subGraph of the view,
   * the first parameter is the name of the new subGraph;
   * the second parameter is the selection of the element to take from the
   * current graph to build the subGraph. If the value of a node or an edge
   * is set up to true, it is added to the subGraph, else it isn't.
   */
  virtual SubGraph* addView(const std::string &name,SelectionProxy *selectionProxy)=0;
  ///Del a view
  virtual void delView(SubGraph *view)=0;
  ///Del a view and all its sub view
  virtual void delAllView(SubGraph *view)=0;
  ///Return the father of this supergraph, if it has no father it returns itself
  virtual SuperGraph* getFather()const =0;
  //==============================================================================
  // Graph manipulation 
  //==============================================================================
  /** 
   *  Add a new node in the current view, and return it. This node is also added in all 
   *  the up_views to maintain the sub_graph relation between views.
   */
  virtual node addNode()=0;
  /** 
   *  Add an existing node in the current view. this node is also added in all 
   *  the up_views to maintain the sub_graph relation between views.
   */
  virtual void addNode(const node)=0;
  /**
   * Add a new edge in the current view, and return it. This edge is also added in all 
   * the up_views to maintain the sub_graph relation between views.
   */
  virtual edge addEdge(const node, const node)=0;
  /**
   *  Add an existing edge in the current view. this edge is also added in all 
   *  the up_views to maintain the sub_graph relation between views.
   */
  virtual void addEdge(const edge )=0;
  ///Delete Node in the current view and in all its sub_views
  virtual void delNode(const node )=0;
  ///Delete Edge in the current view and in all its sub_views
  virtual  void delEdge(const edge )=0;
  /// Delete Node in all the hierarchy of views
  virtual void delAllNode(const node )=0;
  /// Delete Edge in all the hierarchy of views
  virtual  void delAllEdge(const edge )=0;
  /// Return true if the node is element of the graph
  virtual bool isElement(const node )=0;
  /// Return true if the edge is element of the graph
  virtual bool isElement(const edge )=0;
  //================================================================================
  //Iterators on the graph structure.
  //================================================================================
  ///Return an iterator on the nodes of a view.
  virtual Iterator<node>* getNodes()const =0;
  ///Return the ieme in node of n
  virtual node getInNode(const node,unsigned int )const =0;
  ///Return an iterator on the predecessors of a node in the view.
  virtual Iterator<node>* getInNodes(const node)const =0;
  ///Return the ieme out node of n
  virtual node getOutNode(const node,unsigned int )const =0;
  ///Return an iterator on the successors of a node in the view.
  virtual Iterator<node>* getOutNodes(const node)const =0;
  ///Return an iterator on the neighbours of a node in the  view.
  virtual Iterator<node>* getInOutNodes(const node)const =0;
  ///Return an iterator on the edges of a view.
  virtual Iterator<edge>* getEdges()const =0;
  ///Return an iterator on the in-edges of a node in a view.
  virtual Iterator<edge>* getInEdges(const node)const =0;
  ///Return an iterator on the out-edges of a node in a view.
  virtual Iterator<edge>* getOutEdges(const node)const =0;
  ///Return an iterator on the in-out-edges of a node in a view.
  virtual Iterator<edge>* getInOutEdges(const node)const =0;
  //================================================================================
  // Functions for the access to the node informations.
  //================================================================================
  ///return degree of a node in a view
  virtual int deg(const node)const =0;
  ///return indegree of a node in a view
  virtual int indeg(const node)const =0;
  ///return outdegree of a node in a view
  virtual int outdeg(const node)const =0;
  //================================================================================
  // Functions for the acces to the edge informations
  //================================================================================
  ///Return the source of the edge.
  virtual node source(const edge)const =0;
  ///Return the target of the edge.
  virtual node target(const edge)const =0;
  ///Return the opposite node for s in the edge e
  virtual node opposite(const edge, const node)const =0;
  /**
   *  Reverse edge the direction of an edge, the source become the target, and thz target
   *  becomes the source.
   */
  virtual void reverse(const edge)=0;
  //================================================================================
  // Graph Information
  //================================================================================
  ///Return true if the graph is a tree else return false
  virtual bool isTree()=0;
  ///return true if the graph is acyclic else return false
  virtual bool isAcyclic()=0;
  ///Return the number of nodes in the graph
  virtual int numberOfNodes()const =0;
  ///Return the number of edges in the graph
  virtual int numberOfEdges()const =0;
  //Get graph attributes
  virtual DataSet & getAttributes() =0;
};

///Print the graph in ostream, text format
std::ostream& operator<< (std::ostream &,const SuperGraph *);

namespace STL_EXT_NS {
  template<> struct hash<const SuperGraph *> {
    size_t operator()(const SuperGraph *s) const {return size_t(s->getId());}
  };
  template<> struct hash<SuperGraph *> {
    size_t operator()(SuperGraph *s) const {return size_t(s->getId());}
  };
}
#endif
