# -*- coding: utf-8 -*-
# <one line to give the library's name and an idea of what it does.>
# Copyright (C) 2016  <copyright holder> <email>
# 
# 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 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 
#
import logging
import graphrebuilderinterface
import grafon.constants as constants
from grafon.ebuilders import netoneedgebuilder

class PlwnSpikeGraphBuilder(graphrebuilderinterface.GraphRebuilderInterface):
  """
  This class handle NE into built base graph.

  It connects all tokens belongs to the same NE into one node.
  """
  def __init__(self, str_name='PlwnSpikeGraphBuilder'):
    super(PlwnSpikeGraphBuilder, self).__init__(str_name)

  def rebuild_base_graph(self, bgraph):
    """
    For each graph stored into bgraph.graph_dict try to rebuild graph
    with adding synsets connected to disambiguated word

    For rebuild grapgs calls method @see rebuild_graph
    """
    if not bgraph or not bgraph.document:
      return 
    for p in bgraph.document.paragraphs():
      for sentence in p.sentences():
        g = bgraph.graph_dict.get(sentence.id())
        if not g:
          logging.error(
            'There is no graph in PlwnSpikeGraphBuilder builder '
            'for sentence {}'.format(sentence.id()))
          continue
        g = self.rebuild_graph(bgraph, g, sentence)
        bgraph.graph_dict[sentence.id()] = g

  def rebuild_graph(self, bgraph, g, sentence):
    """
    This function rebuilds given graph based on the connection to 
    disambiguated words with informations into nodes. 
    Returns rebuilded graph.

    @param bgraph Base graph
    @type bgraph: BaseGraph
    @param g Built graph
    @type g: networkx.MultiDiGraph
    @param sentence Based on the this senence given graph (g) has been built
    @type sentence: corpus2.Sentence
    @return rebuilded graph
    @rtype: networkx.MultiDiGraph
    """
    sgraph = bgraph.resources[constants.RESOURCES_PLWN_HNDL]
    for t in sentence.tokens():
      md = t.get_metadata()
      if not md:
        continue
      synid = md.get_attribute(constants.TOKEN_SENSE_UKB_SYNSET_ID)
      if not synid:
        continue
      synid = int(synid)
      if not sgraph.G().has_node(synid):
        continue
      in_edges  = sgraph.G().in_edges (synid, data=True)
      out_edges = sgraph.G().out_edges(synid, data=True)
      for k in bgraph.node_converter.key(t):
        if not g.has_node(k):
          k = '{} się'.format(k.encode('utf-8')).decode('utf8')
          if not g.has_node(k):
            continue
        for fn, tn, d in in_edges:
          if not g.has_node(fn):
            g.add_node(fn, attr_dict = {
              constants.NODE_TOKENS   : [],
              constants.NODE_COUNT    : 1,
              constants.NODE_PLWN_STR : sgraph.G().node[fn][constants.NODE_PLWN_STR],
              constants.NODE_SOURCES  : [constants.NODE_FROM_PLWN]})
          g.add_edge(k, fn, attr_dict = d)
        for fn, tn, d in out_edges:
          if not g.has_node(tn):
            g.add_node(tn, attr_dict = {
              constants.NODE_TOKENS   : [],
              constants.NODE_COUNT    : 1,
              constants.NODE_PLWN_STR : sgraph.G().node[tn][constants.NODE_PLWN_STR],
              constants.NODE_SOURCES  : [constants.NODE_FROM_PLWN]})
          g.add_edge(tn, k, attr_dict = d)
    return g