/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package FunctionLayer;

import edu.mit.jmwe.data.IMWE;
import edu.mit.jmwe.data.IToken;
import edu.mit.jmwe.data.Token;
import edu.mit.jmwe.detect.CompositeDetector;
import edu.mit.jmwe.detect.Consecutive;
import edu.mit.jmwe.detect.Exhaustive;
import edu.mit.jmwe.detect.IMWEDetector;
import edu.mit.jmwe.detect.InflectionPattern;
import edu.mit.jmwe.detect.MoreFrequentAsMWE;
import edu.mit.jmwe.detect.ProperNouns;
import edu.mit.jmwe.index.IMWEIndex;
import edu.mit.jmwe.index.MWEIndex;
import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.ling.CoreLabel;
import edu.stanford.nlp.ling.JMWEAnnotation;
import edu.stanford.nlp.pipeline.Annotation;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import edu.stanford.nlp.util.CoreMap;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @author install1
 */
//maybe not public?
public class PipelineJMWESingleton {

    //if not needed to be volatile dont make it, increases time
    //public volatile static PipelineJMWESingleton INSTANCE;
    public static PipelineJMWESingleton INSTANCE;
    private static StanfordCoreNLP localNLP = initializeJMWE();
    private static String underscoreSpaceReplacement;
    private static IMWEIndex index;
    private static IMWEDetector detector;

    private PipelineJMWESingleton() {
        String jmweIndexData = "/home/nonroot/autism_bot/lib/mweindex_wordnet3.0_semcor1.6.data"; // ./lib/mweindex_wordnet3.0_semcor1.6.data
        String jmweIndexDataLocalTest = "E:/stationær backup filer/Projects/mweindex_wordnet3.0_semcor1.6.data";
        File indexFile = new File((String) jmweIndexData);
        index = new MWEIndex(indexFile);
        String detectorName = "Exhaustive";
        try {
            index.open();
        } catch (IOException e) {
            throw new RuntimeException("unable to open IMWEIndex index: " + e + "\n");
        }
        detector = getDetector(index, detectorName);
        //index.close();
    }

    public static void getINSTANCE() {
        INSTANCE = new PipelineJMWESingleton();
    }

    public final Annotation getJMWEAnnotation(String str) {
        try {
            index.open();
        } catch (IOException e) {
            throw new RuntimeException("unable to open IMWEIndex index: " + e + "\n");
        }
        Annotation annoStr = new Annotation(str);
        localNLP.annotate(annoStr);
        Class<CoreAnnotations.SentencesAnnotation> sentencesAnnotationClass = CoreAnnotations.SentencesAnnotation.class;
        for (CoreMap sentence : annoStr.get(sentencesAnnotationClass)) {
            List<IMWE<IToken>> mwes = getjMWEInSentence(sentence, index, detector, false);
            //annoStr.set(JMWEAnnotation.class, mwes);
            sentence.set(JMWEAnnotation.class, mwes);
        }
        //index.close();
        return annoStr;
    }

    public final static StanfordCoreNLP initializeJMWE() {
        Properties propsJMWE;
        propsJMWE = new Properties();
        propsJMWE.setProperty("annotators", "tokenize,ssplit,pos,lemma");
        propsJMWE.setProperty("tokenize.options", "untokenizable=firstKeep");
        propsJMWE.setProperty("threads", "2");
        propsJMWE.setProperty("pos.maxlen", "90");
        propsJMWE.setProperty("tokenize.maxlen", "90");
        propsJMWE.setProperty("ssplit.maxlen", "90");
        propsJMWE.setProperty("lemma.maxlen", "90");
        underscoreSpaceReplacement = "-";
        localNLP = new StanfordCoreNLP(propsJMWE);
        System.out.println("finished JMWE constructor \n");
        return localNLP;
    }

    public IMWEDetector getDetector(IMWEIndex index, String detector) {
        IMWEDetector iMWEdetector = null;
        switch (detector) {
            case "Consecutive":
                iMWEdetector = new Consecutive(index);
                break;
            case "Exhaustive":
                iMWEdetector = new Exhaustive(index);
                break;
            case "ProperNouns":
                iMWEdetector = ProperNouns.getInstance();
                break;
            case "Complex":
                iMWEdetector = new CompositeDetector(ProperNouns.getInstance(),
                        new MoreFrequentAsMWE(new InflectionPattern(new Consecutive(index))));
                break;
            case "CompositeConsecutiveProperNouns":
                iMWEdetector = new CompositeDetector(new Consecutive(index), ProperNouns.getInstance());
                break;
            default:
                throw new IllegalArgumentException("Invalid detector argument " + detector
                        + ", only \"Consecutive\", \"Exhaustive\", \"ProperNouns\", \"Complex\" or \"CompositeConsecutiveProperNouns\" are supported.");
        }
        return iMWEdetector;
    }

    public List<IMWE<IToken>> getjMWEInSentence(CoreMap sentence, IMWEIndex index, IMWEDetector detector,
                                                boolean verbose) {
        List<IToken> tokens = getITokens(sentence.get(CoreAnnotations.TokensAnnotation.class));
        List<IMWE<IToken>> mwes = detector.detect(tokens);
        if (verbose) {
            for (IMWE<IToken> token : mwes) {
                System.out.println("IMWE<IToken>: " + token);
            }
        }
        return mwes;
    }

    public List<IToken> getITokens(List<CoreLabel> tokens) {
        return getITokens(tokens, underscoreSpaceReplacement);
    }

    public List<IToken> getITokens(List<CoreLabel> tokens, String underscoreSpaceReplacement) {
        List<IToken> sentence = new ArrayList<IToken>();
        for (CoreLabel token : tokens) {
            sentence.add(new Token(token.originalText().replaceAll("_", underscoreSpaceReplacement).replaceAll(" ", underscoreSpaceReplacement), token.get(CoreAnnotations.PartOfSpeechAnnotation.class), token.lemma().replaceAll("_", underscoreSpaceReplacement).replaceAll(" ", underscoreSpaceReplacement)));
        }
        return sentence;
    }
}
