"""
.. A wrapper for the Analyzer. It runs it as an XML-RPC server to isolate from 
    lengthy grammar-building times.

.. moduleauthor:: Luca Gilardi <lucag@icsi.berkeley.edu>


------
See LICENSE.txt for licensing information.
------

"""

import sys
from utils import Struct, update, display  # @UnusedImport
from xmlrpclib import ServerProxy  # @UnresolvedImport
from SimpleXMLRPCServer import SimpleXMLRPCServer  # @UnresolvedImport
from utils import interpreter
from pprint import pprint
from xmlrpclib import Fault
import time
from threading import Thread


# Possibly change this for your system
dll = {'linux': '/jre/lib/amd64/server/libjvm.so', 
       'darwin': '/jre/lib/server/libjvm.dylib',
       'win32': '/jre/bin/server/jvm.dll'}

try:
    import jpype, os  # @UnresolvedImport
    jpype.startJVM(os.environ['JAVA_HOME'] + dll[sys.platform],
                   '-ea', '-Xmx5g', '-Djava.class.path=lib/compling.core.jar')
    compling = jpype.JPackage('compling')
    SlotChain = getattr(compling.grammar.unificationgrammar, 'UnificationGrammar$SlotChain')
    getParses = compling.gui.util.Utils.getParses
    ParserException = jpype.JException(compling.parser.ParserException)  # @UnusedVariable
    ECGAnalyzer = compling.parser.ecgparser.ECGAnalyzer
    getDfs = compling.grammar.unificationgrammar.FeatureStructureUtilities.getDfs  # @UnusedVariable
except ImportError:
    from compling.grammar.unificationgrammar.UnificationGrammar import SlotChain
    from compling.gui.util.Utils import getParses
    from compling.parser import ParserException  # @UnusedImport
    from compling.parser.ecgparser import ECGAnalyzer
    from compling.grammar.unificationgrammar.FeatureStructureUtilities import getDfs  # @UnusedImport
    from compling.gui import AnalyzerPrefs
    from compling.grammar.ecg.Prefs import Property
    from compling.gui.AnalyzerPrefs import AP




class Analyzer(object):
    def __init__(self, prefs):
        self.analyzer = ECGAnalyzer(prefs)
        self.grammar = self.analyzer.grammar
        self.server = None


    def get_mappings(self):
        mappings = self.analyzer.getMappings()
        m = dict()
        for entry in mappings.entrySet():
            m[entry.key] = entry.value
        return m

    def get_lexicon(self):
        lexes = self.analyzer.getLexicon()
        return list(lexes)


    def get_utterances(self):
        utterances = self.analyzer.getUtterances()
        return list(utterances)

    def get_parses(self, sentence):
        try:
            return getParses(sentence, self.analyzer)
        except ParserException, p:
            print(p.message)
            raise Fault(-1, p.message)

    def test_analysis(self, analysis):
        """ For testing how to output spans, etc. In development. 
        Mostly just a way to store info about methods. """
        featureStruct = analysis.featureStructure
        slots = featureStruct.slots.toArray()  # Puts slots into array
        first = slots[0]  # Get first slot, e.g. ROOT
        entries = first.features.entrySet().toArray() # Puts features into entry set
        value = entries[0].value # Gets actual value, e.g. EventDescriptor[2]



    def get_mapping(self):
        v = AP.valueOf("MAPPING_PATH")
        return self.analyzer.getPrefs().getSetting(v)

        
    def parse(self, sentence):
        def root(parse):
            return parse.analyses[0].featureStructure.mainRoot
        
        def as_sequence(parse):
            def desc(slot):
                return (slot_type(slot), slot_index(slot), slot_typesystem(slot), slot_value(slot))
            
            slots = dict()
            root_ = root(parse)
            seq = [(parent, role) + desc(slots[s_id]) for parent, role, s_id in dfs('<ROOT>', root_, None, slots) if parent != -1]