#
# <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 networkx
import similarity
import sidddescriptormeasure
import metasimilaritymeasure
import grafon.constants as constants
import grafon.spreading.splashspreading as splashspreading

class SIDDSplashDescriptorsMeasure(
  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.
  In case when the propagated value came from two or more differen nodes,
  then these values are summed.
  """

  def __init__(self, options, str_name = 'SIDDSplashDescriptorsMeasure'):
    """!
    Constructor

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

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

    For each node which is into g1 and g2 calculates the SIDD and 
    returns the sum of its. This method uses spreading values into graph
    from module grafon.spreading.splashspreading. The number of iteration
    has been set to 3 and maximum depth into graph also to 3.

    @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=splashspreading.SplashSpreading(),
      spread_max_it=constants.SPLASH_MAX_ITER,
      spread_max_depth=constants.SPLASH_MAX_DEPTH,
      init_values=dict_node_descr,
      str_name=self.__str__())

    return meta.calculate(g1, g2)