#!/usr/bin/env python
# PYTHON_ARGCOMPLETE_OK
import sys
import argparse
import ConfigParser
from StringIO import StringIO
from npsemrel.carrot.db import db
from plumper.sumo.processor import SumoProcessor
try:
    import argcomplete
except ImportError:
    argcomplete = None

class SumoStaticProcessor(SumoProcessor):
    def __init__(self, db_config, senseindexfile, senseindexfiles,
                 plwn2sumo_map_file, sumo_graph_file, tagset='nkjp',
                 sumo_hiper = False, sumo_specific_concept = False,
                 sumo_subjective_assessment = False):
        self.plwn2sumo_map_file = plwn2sumo_map_file
        self.sumo_graph_file = sumo_graph_file
        self.tagset = tagset
        self.sumo_hiper = sumo_hiper
        self.sumo_specific_concept = sumo_specific_concept
        self.sumo_subjective_assessment = sumo_subjective_assessment
        self.dbcon = db.DB()
        self.dbconnection = self.dbcon.connect(db_config)
        if not self.dbconnection:
            print >> sys.stderr, 'Cannot connect to DB!'
            exit(1)

        self.sumo_out = None
    
        print >> sys.stderr, 'Reading static plWN2SUMO mapping file...',
        with open(plwn2sumo_map_file, 'rt') as fin:
            self.make_sumo_map(fin)
        print >> sys.stderr, ' done'


    def make_sumo_map(self, in_file):
        self.sumo_out={}
        for line in in_file:
            spl_line = line.split(';')
            syn_id = spl_line[2]
            concept = spl_line[8].encode('utf-8')
            sumo_rel = spl_line[-1]
            if syn_id in self.sumo_out:
                l = self.sumo_out[syn_id].split(';')
                l.append('%s:%s' % (sumo_rel, concept))
                l = list(set(l))
                self.sumo_out[syn_id] = ';'.join(l)
            else:
                self.sumo_out[syn_id] = "%s:%s" % (sumo_rel, concept)


    def get_not_mapped_synsets(self, document):
        not_mapped_synsets = set()
        for paragraph in document.paragraphs():
            for sentence in paragraph.sentences():
                for token in sentence.tokens():
                    md = token.get_metadata()
                    if md:
                        ukb_syn_id = md.get_attribute('sense:ukb:syns_id')
                        if ukb_syn_id and not ukb_syn_id in self.sumo_out:
                            not_mapped_synsets.add(ukb_syn_id)
        return not_mapped_synsets


    def serdel_step(self, document, inbuf, not_mapped_synsets):
        from plumper.tools.mapping.serdel import Serdel
        serdel = Serdel(self.dbconnection)
        out = StringIO()
        serdel.serdluj_z_tym(inbuf, out, False, not_mapped_synsets)

        return out


    def corec_step(self, inbuf):
        from plumper.tools.mapping.corec import Corec
        corec = Corec(self.sumo_graph_file)
        out = StringIO()
        corec.zakorkuj_mi_to(inbuf, out)

        return out


    def rubin_step(self, inbuf):
        from plumper.tools.mapping.rubin import Rubin
        rubin = Rubin()
        out = StringIO()
        rubin.szlifuj(inbuf, out)

        return out


    def process_document(self, document):
        if self.sumo_hiper or self.sumo_specific_concept or self.sumo_subjective_assessment:
            temp = StringIO()
            inbuf = self.plwn2sumo_map_file

            is_use = False
            
            if self.sumo_hiper:
                not_mapped_synsets = set()
                not_mapped_synsets = self.get_not_mapped_synsets(document)
                if not_mapped_synsets:
                  n_temp = StringIO(temp.getvalue().decode('utf-8'))
                  temp = self.serdel_step(document, inbuf, not_mapped_synsets) \
                         if not is_use \
                         else self.serdel_step(document, n_temp, not_mapped_synsets)
                  is_use = True
            if self.sumo_specific_concept:
                n_temp = StringIO(temp.getvalue().decode('utf-8'))
                temp = self.corec_step(inbuf) \
                       if not is_use \
                       else self.corec_step(n_temp)
                is_use = True
            if self.sumo_subjective_assessment:
                n_temp = StringIO(temp.getvalue().decode('utf-8'))
                temp = self.rubin_step(inbuf) \
                       if not is_use \
                       else self.rubin_step(n_temp)
                is_use = True

            self.make_sumo_map(temp.getvalue().split('\n')[1:-1])

        for paragraph in document.paragraphs():
            for sentence in paragraph.sentences():
                for token in sentence.tokens():
                    md = token.get_metadata()
                    if md:
                        ukb_syn_id = md.get_attribute('sense:ukb:syns_id')
                        if ukb_syn_id and ukb_syn_id in self.sumo_out:
                            md.set_attribute('sumo_map', 
                                             self.sumo_out[ukb_syn_id])
        return document


def aparser():
    arg_parser = argparse.ArgumentParser(description='Sumo mapping tool for' +
                                                     ' ccl files')
    arg_parser.add_argument('input_file', help='input file. If you want' +
                                               ' to use stdin use "-"')
    arg_parser.add_argument('-o', '--output', help='output file path if not' +
                                                   ' present script will' +
                                                   ' print to stdout')
    arg_parser.add_argument('-c', '--config', required=True,
                            help='path to sumo config file')
    if argcomplete:
        argcomplete.autocomplete(arg_parser)
    return arg_parser.parse_args()


def main():
    args = aparser()
    config = ConfigParser.RawConfigParser()
    config.readfp(open(args.config))
    proc = SumoStaticProcessor(config.get('sumo', 'db_config'),
                            config.get('sumo', 'sense_index_file'),
                            config.get('sumo', 'sense_index_files').split(),
                            config.get('sumo', 'plwn2sumo_map_file'),
                            config.get('sumo', 'sumo_graph_file'),
                            config.get('sumo', 'tagset'),
                            config.getboolean('sumo', 'sumo_hiper'),
                            config.getboolean('sumo', 'sumo_specific_concept'),
                            config.getboolean('sumo', 'sumo_subjective_assessment'))
    proc.process_ccl(args.input_file, args.output if args.output else None)


if __name__ == '__main__':
    main()
