#!/usr/bin/python
# -*- coding: utf-8 -*-
#PYTHON_ARGCOMPLETE_OK

# <one line to give the library's name and an idea of what it does.>
# Copyright (C) 2014  <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/>.
#

__doc__ = '''
Dla zadanego pliku z opisem relacji między fragmentami tekstów buduje grafy
i oblicza podobieństwo. Z zadanego pliku relacji odczytuje kolejne relacje,
w pliku ccl odnajduje zdania i dla tych zdań (grafów) oblicza podobieństwo
uwzględniając miary (i ustawienia) z pliku konfiguracyjnego, po czym zapisuje 
wyjście do pliku lub na stdout (jesli nie podano pliku wyjściowego).

Całość obliczana jest dla zadanego pliku relccl i grafy budowane są w locie.
Jeżeli podano ścieżkę do katalogu z grafami, grafy są wczytywane, nie są 
budowane w locie!

Przykład uruchomienie z wczytywaniem grafów z zadanego katalogu:

python bet_ent_sim.py \
  -f /mnt/dane_eksperymenty/entailment/new-2015-09/not-sampled-separated/output.xml \
  -r /mnt/dane_eksperymenty/entailment/new-2015-09/not-sampled-separated/with-other-rels-fixed/Źródło-fixed.rel.xml \
  -c ~/repos/grafon/cfg/grafon.ini \
  -wgd /mnt/dane_eksperymenty/entailment/grafon-experiments/wikinews-graphs/simple \
  -o simple-zrodlo.csv

'''

import os, sys
from grafon import grafon_base
from grafon.graphs.basegraph import BaseGraph
from grafon.utils.grafonconfig import GrafonConfig
from grafon.gbuilders.graphbuilder import GraphBuilder

try:
  import argcomplete
except ImportError:
  argcomplete = None
def make_parser(desc = ''):
  """
  Makes base parser for entailment
  """
  aparser = grafon_base.make_parser(desc)
  aparser.add_argument('-f', '--cclfile', dest='ccl',
                       required=True, type=str,
                       help=(
                         'Ccl file. For each sentences into file, '
                         'the graph will be build.'))
  aparser.add_argument('-r', '--relcclfile', dest='relccl',
                       required=True, type=str,
                       help=(
                         'Relccl file. Depends on the edge '
                         'builders relccl file may be used for build edges.'))
  aparser.add_argument('-o', '--out-res-file', dest = 'out_res_file',
                       required=False, help=(
                         'If options is given then '
                         'then the results will be stroed into given filename. '
                         'If not gvien then the result will be stored into '
                         'standard output.'))
  aparser.add_argument('-wgd', '--wiki-graphs-dir', dest='wiki_graph_dir',
                       help=('If option is given, then the graphs are not '
                         'built in the fly but only reads from given '
                         'director. It can be faster thar built in the fly. '
                         'Direcory should contains graphs buit from wikinews.'))
  if argcomplete:
    argcomplete.autocomplete(aparser)
  return aparser

def calculate_print_measures(
  measures, bg, graphs_dict, ofilename = None, accepted_resl = []):
  # Out stream
  out = sys.stdout if not ofilename else open(ofilename, 'wt')

  # write header
  out.write('S1;S2;')
  for m in measures:
    out.write('%s;' % m)
  out.write('\n')

  # dictionary of available sentences
  sentences = dict()
  for p in bg.document.paragraphs():
    for s in p.sentences():
      sentences[s.id()] = "\"%s\""%' '.join(
        t.orth_utf8().replace(';', '. ').replace('"', '\'') 
        for t in s.tokens())

  # calculate similarity between all pair of sentences
  for r in bg.document.relations():
    rname = r.rel_name().strip()
    if len(accepted_resl) and not rname in accepted_resl:
      continue
    
    print rname
    sid_from = r.rel_from().sentence_id()
    sid_to = r.rel_to().sentence_id()
    s_from = sentences.get(sid_from, None)
    s_to = sentences.get(sid_to, None)
    
    print "FROM: ", sid_from
    print "TO  : ", sid_to
    print 60 * '#'
    
    g_from = graphs_dict.get(sid_from, None)
    g_to = graphs_dict.get(sid_to, None)
    if not g_from or not g_to or not s_from or not s_to:
      print '????????????'
      continue
    out.write('%s;%s; ' % (s_from, s_to))
    for m in measures:
      v = m.calculate(g_from, g_to)
      out.write('%f;' % v)
    out.write('\n')
  out.close()

def main(argv = None):
  p = make_parser(__doc__)
  args = p.parse_args(argv)
  cfg = GrafonConfig(args.config)

  tagset = cfg.tagset()
  node = cfg.node(tagset)
  filters = cfg.filters(tagset)

  bg = BaseGraph(node, filters)
  smerger = cfg.sumo_merger(bg)
  pmerger = cfg.plwn_merger(bg)

  bgbuilder = GraphBuilder()
  relccl = args.relccl if os.path.exists(args.relccl) else args.ccl
  if not args.wiki_graph_dir:
    sgraph    = grafon_base.read_sumo_graph(cfg) if smerger else None
    plwngraph = grafon_base.read_plwn_graph(cfg) if pmerger else None
    reducers  = cfg.reducers() if cfg.reducers() else None

    try:
      print >> sys.stderr, 'Building base graphs...'
      bgbuilder.build_graph_for_rel_sentences(
        bg, args.ccl, relccl, tagset, cfg.accepted_relations())
    except Exception, e:
      print >> sys.stderr, "Exception:", e
      return 0

    for ebuilder in cfg.ebuilders():
      print >> sys.stderr, 'Adding edges into base graph using builder', ebuilder
      ebuilder.add_edges(bg)

    all_graphs = grafon_base.merge_graphs_to_dict(
      bg, smerger, sgraph, pmerger, plwngraph, reducers)
  else:
    print >> sys.stderr, 'Loading graphs...'
    bgbuilder.load_graps_for_rel_sentences(bg, args.ccl, relccl, tagset, 
      cfg.accepted_relations(), args.wiki_graph_dir)
    all_graphs = bg.graph_dict

  print >> sys.stderr, 'Calculating similarities...'
  calculate_print_measures(cfg.measures(), bg, all_graphs, 
                           args.out_res_file, cfg.accepted_relations())

  if args.visualise_dir:
    grafon_base.save_graphs_into_files(bg, all_graphs, args.visualise_dir)

if __name__ == '__main__':
  main()