#
# <one line to give the library's name and an idea of what it does.>
# Copyright (C) 2015  <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 sys
import networkx
import similarity
import sidddescriptormeasure
import metasimilaritymeasure
import grafon.constants as constants
import grafon.spreading.pagerankspreading as pagerankspreading

class SIDDPagerakDescriptorsMeasure(
  sidddescriptormeasure.SIDDDescriptorMeasure):
  """!
  Calcualtes the similarity based on the nodes decriptors.

  As a value is returned cosine similarity between two vectors v1 and v2.
  V1 is build from first graph and V2 from second graph. As the first step
  SIID is calculated for each common nodes from g1 and g2. Next, the
  description value is propagated to neighbors of nodes with descriptors using
  PageRank algorith. The ranking is used as the base to built vectors 
  to calculate similarity.
  """

  def __init__(self, options, str_name = 'SIDDPagerakDescriptorsMeasure'):
    """!
    Constructor calls parents constructor ;)

    @param options: a dictionary containing options for this measure
    @para str_name: default value same as the class name 
                    "SIDDPagerakDescriptorsMeasure"
    """
    sidddescriptormeasure.SIDDDescriptorMeasure.__init__(
      self, options, str_name)


  def calculate(self, g1, g2):
    """!
    Implementation of abstract calculate function from interface. 

    For each node into g1 and g2 calculates SIDD value and put it as node 
    value. Next calculates the PageRank with initialized Page Rank vector 
    with calculated values. PageRank rankings are converted to vectors and
    between them Cosine similarity is calclculates. This function uses 
    metameasure to initialize them with cosine function and pagerank 
    spreading method.

    @param g1 first graph
    @type g1: networgx.DiGraph/networkx.MultiDiGraph

    @param g2 second graph
    @type g1: networgx.DiGraph/networkx.MultiDiGraph

    @return Sum of SIDD
    @rtype: double
    """
    if not g1 or not g2:
      return 0
    # dictionary where as the key is used node which appear into both graphs
    dict_node_descr = self.prepare_node_descriptor_dictionary(g1, g2)
    if not len(dict_node_descr):
      return 0

    # metameasure initialized with cosine similarity and PageRank spreading
    meta = metasimilaritymeasure.MetaSimilarityMeasure(
      options=self.options(), 
      sim_funcion=similarity.CosineSimilarity(),
      spread_method=pagerankspreading.PageRankSpreading(),
      spread_max_it=constants.PAGE_RANK_MAX_ITER,
      spread_max_depth=1,
      init_values=dict_node_descr,
      str_name=self.__str__())

    return meta.calculate(g1, g2)