package cz.brmlab.yodaqa.analysis.answer;

import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.tcas.Annotation;
import org.apache.uima.resource.ResourceInitializationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cz.brmlab.yodaqa.analysis.ansscore.AnswerFV;
import cz.brmlab.yodaqa.model.CandidateAnswer.AF_LATNE;
import cz.brmlab.yodaqa.model.CandidateAnswer.AnswerFeature;
import cz.brmlab.yodaqa.model.CandidateAnswer.AnswerInfo;
import cz.brmlab.yodaqa.model.Question.Focus;
import cz.brmlab.yodaqa.model.TyCor.LAT;
import cz.brmlab.yodaqa.model.TyCor.NELAT;
import cz.brmlab.yodaqa.provider.OpenNlpNamedEntities;

import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.NN;
import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.POS;
import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;

/**
 * Generate LAT annotations in a CandidateAnswerCAS. If a NamedEntity
 * covers the answer focus, the type of that named entity (as not just
 * a word but a wordnet synset) is generated as the LAT. */

public class LATByNE extends JCasAnnotator_ImplBase {
	final Logger logger = LoggerFactory.getLogger(LATByNE.class);

	public void initialize(UimaContext aContext) throws ResourceInitializationException {
		super.initialize(aContext);
	}

	public void process(JCas jcas) throws AnalysisEngineProcessException {
		for (Focus focus : JCasUtil.select(jcas, Focus.class)) {
			addNELAT(jcas, focus);
		}
	}

	protected boolean addNELAT(JCas jcas, Focus focus) throws AnalysisEngineProcessException {
		boolean ne_found = false;
		for (NamedEntity ne : JCasUtil.selectCovering(NamedEntity.class, focus)) {
			ne_found = true;
			long synset = OpenNlpNamedEntities.neValueToSynset(ne.getValue());
			addLAT(new NELAT(jcas), ne.getBegin(), ne.getEnd(), ne, ne.getValue(), focus.getToken().getPos(), synset, 0.0);
			logger.debug(".. LAT {}/{} by NE {}", ne.getValue(), synset, ne.getCoveredText());
			addLATFeature(jcas, AF_LATNE.class);
		}
		return ne_found;
	}

	protected void addLAT(LAT lat, int begin, int end, Annotation base, String text, POS pos, long synset, double spec) {
		lat.setBegin(begin);
		lat.setEnd(end);
		lat.setBase(base);
		lat.setPos(pos);
		lat.setText(text);
		lat.setSpecificity(spec);
		lat.setSynset(synset);
		lat.addToIndexes();
	}

	protected void addLATFeature(JCas jcas, Class<? extends AnswerFeature> f) throws AnalysisEngineProcessException {
		AnswerInfo ai = JCasUtil.selectSingle(jcas, AnswerInfo.class);
		AnswerFV fv = new AnswerFV(ai);
		fv.setFeature(f, 1.0);

		for (FeatureStructure af : ai.getFeatures().toArray())
			((AnswerFeature) af).removeFromIndexes();
		ai.removeFromIndexes();

		ai.setFeatures(fv.toFSArray(jcas));
		ai.addToIndexes();
	}
}

@@ -36,16 +36,46 @@
 nswer;%0A%0A
+import java.util.Collection;%0A%0A
 import o
@@ -940,71 +940,8 @@
 s;%0A%0A
-import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.NN;%0A
 impo
@@ -1647,16 +1647,204 @@
 ption %7B%0A
+%09%09/* With no focus, make good with any NamedEntity inside. */%0A%09%09if (JCasUtil.select(jcas, Focus.class).isEmpty()) %7B%0A%09%09%09addNELAT(jcas, null, JCasUtil.select(jcas, NamedEntity.class));%0A%09%09%7D%0A%0A
 %09%09for (F
@@ -1917,16 +1917,67 @@
 s, focus
+, JCasUtil.selectCovering(NamedEntity.class, focus)
 );%0A%09%09%7D%0A%09
@@ -2029,16 +2029,45 @@
 us focus
+, Collection%3CNamedEntity%3E NEs
 ) throws
@@ -2156,57 +2156,11 @@
 e : 
-JCasUtil.selectCovering(NamedEntity.class, focus)
+NEs
 ) %7B%0A
@@ -2179,16 +2179,17 @@
 = true;%0A
+%0A
 %09%09%09long 
@@ -2246,24 +2246,320 @@
 etValue());%0A
+%09%09%09POS pos = null;%0A%09%09%09if (focus != null) %7B%0A%09%09%09%09pos = focus.getToken().getPos();%0A%09%09%09%7D else %7B%0A%09%09%09%09/* the last token covered by a NamedEntity%0A%09%09%09%09 * (i.e. a noun if at all possible. */%0A%09%09%09%09for (Token t : JCasUtil.selectCovered(Token.class, ne))%0A%09%09%09%09%09pos = t.getPos();%0A%09%09%09%09assert(pos != null);%0A%09%09%09%7D%0A%0A
 %09%09%09addLAT(ne
@@ -2624,33 +2624,11 @@
 (), 
-focus.getToken().getPos()
+pos
 , sy
@@ -2725,16 +2725,17 @@
 ext());%0A
+%0A
 %09%09%09addLA

answer LATByNE: Handle a no-focus situation