import networkx
from grafon.graphs import semgraph
import grafon.constants as constants

class SumoGraph(semgraph.SemGraph):
  """!
  This class is the child of SemGraph and imeplements all abstract methods.
  The inherited method build_graph is throwin the exception. For built the
  graph, sould be called method build_graph(filename).

  It is helper class for read the sumo graph stored into text file. Text file
  is in column-like csv format with ';' as separator:

  Concepet1;Concept2;RelationBetweenConcepts1-2
  (...)
  ConcepetN;ConceptK;RelationBetweenConceptsN-K

  That means:
    Concepet1 -> RelationBetweenConcepts1-2 -> Concept2
    (...)
    ConcepetN -> RelationBetweenConceptsN-K -> ConceptK
  """

  def __init__(self):
    """!
    Constructor only calls parent constructor
    """
    super(SumoGraph, self).__init__()

  def build_graph(self):
    """!
    This method (built_graph for SumoGraph) must be called with the path 
    to stored sumo graph into file.
    """
    raise NotImplementedError(
      "SumoGraph: You should call built_graph with the path to graph file")

  def build_graph(self, filename):
    """!
    Overwrited function to build graph in networkx format based
    on the stored sumo graph into csv format. 

    It makes two graphs, first is directed graph with the directions same 
    as relations into SUMO, and second is undirected graph.

    @param: filename path to file with stored sumo graph
    """
    self._g = networkx.DiGraph()
    with open(filename, 'rt') as fg:
      for line in fg:
        n1, n2, rel = line.strip().split(';')[0:3]
        if not self._g.has_node(n1):
          self._g.add_node(n1, attr_dict = {
            constants.NODE_TOKENS       : [],
            constants.NODE_COUNT        : 1,
            constants.NODE_SOURCES      : [constants.NODE_FROM_SUMO]})
        if not self._g.has_node(n2):
          self._g.add_node(n2, attr_dict = { 
            constants.NODE_TOKENS       : [],
            constants.NODE_COUNT        : 1,
            constants.NODE_SOURCES      : [constants.NODE_FROM_SUMO]})
        self._g.add_edge(
                n1, n2, 
                attr_dict={
                  constants.EDGE_LABEL: rel,
                  constants.EDGE_COUNT: 1})
    self._undirected_g = self._g.to_undirected()
