package org.studiorailgun.ai.conversation.evaluators.query;

import java.util.Iterator;
import java.util.Set;

import org.studiorailgun.ai.conversation.parser.PennTreebankTagSet;
import org.studiorailgun.ai.conversation.parser.bank.LemmaBank;
import org.studiorailgun.ai.conversation.parser.depend.Clause;
import org.studiorailgun.ai.conversation.parser.depend.Predicate;
import org.studiorailgun.ai.conversation.tracking.Conversation;
import org.studiorailgun.ai.conversation.tracking.Quote;
import org.studiorailgun.ai.conversation.tracking.Sentence;

import edu.stanford.nlp.ling.IndexedWord;
import edu.stanford.nlp.semgraph.SemanticGraph;

/**
 * Evaluates queries
 */
public class QueryEval {
    
    /**
     * Evaluates a quote
     * @param conversation The conversation
     * @param quote The quote
     */
    public static void evaluate(Conversation conversation, Quote quote, Sentence sentence){
        SemanticGraph semanticGraph = sentence.getGraph();
        Clause mainClause = sentence.getMainClause();
        Predicate predicate = mainClause.getPredicate();

        String predicateTag = predicate.getRoot().tag();
        
        if(predicate.getCopular() != null){
            QueryEval.evaluateCopular(conversation,quote,sentence);
        } else if(PennTreebankTagSet.isVerb(predicateTag)){
            if(PennTreebankTagSet.isBe(predicateTag)){
                QueryEval.evaluateBe(conversation, quote, sentence);
            } else {
                String message = "Unsupported predicate type!\n" +
                "\"" + sentence.getRaw() + "\"\n" +
                semanticGraph;
                throw new UnsupportedOperationException(message);
            }
        } else {
            String message = "Unsupported predicate type!\n" +
                "\"" + sentence.getRaw() + "\"\n" +
                semanticGraph;
            throw new UnsupportedOperationException(message);
        }
    }

    /**
     * Evaluates a copular sentence
     * @param conversation The conversation
     * @param quote The quote
     * @param sentence The sentence
     */
    private static void evaluateCopular(Conversation conversation, Quote quote, Sentence sentence){
        Clause mainClause = sentence.getMainClause();
        Predicate predicate = mainClause.getPredicate();
        IndexedWord copular = predicate.getCopular();
        String lemma = LemmaBank.getLemma(copular.originalText());
        switch(lemma){
            case "be": {
                QueryEval.evaluateBe(conversation, quote, sentence);
            } break;
            default: {
                throw new Error("Unhandled copular verb type! lemma: " + lemma + " original: " + copular.originalText());
            }
        }
    }

    /**
     * Evaluates an equivalence query
     * @param conversation The conversation
     * @param quote The quote
     */
    private static void evaluateBe(Conversation conversation, Quote quote, Sentence sentence){
        //get the two things we're comparing
        SemanticGraph graph = sentence.getGraph();
        IndexedWord root = graph.getFirstRoot();
        Set<IndexedWord> children = graph.getChildren(root);
        Iterator<IndexedWord> iterator = children.iterator();
        IndexedWord firstItem = iterator.next();
        IndexedWord secondItem = iterator.next();
        NounStack firstNoun = NounStack.parse(graph, firstItem);
        NounStack secondNoun = NounStack.parse(graph, secondItem);

        //interrogative error checking
        if(firstNoun.interrogative != null && secondNoun.interrogative != null){
            String message = "Comparing two interrogatives!";
            throw new Error(message);
        }

        //handle interrogative solving
        if(firstNoun.interrogative != null || secondNoun.interrogative != null){
            NounStack interrogativeStack = firstNoun.interrogative != null ? firstNoun : secondNoun;
            NounStack qualifierStack = firstNoun.interrogative != null ? secondNoun : firstNoun;

            switch(interrogativeStack.interrogative.toLowerCase()){
                case "which": {
                    Interrogative.evalWhichQuery(conversation, quote, sentence, interrogativeStack, qualifierStack);
                } break;
                case "what": {
                    Interrogative.evalWhatQuery(conversation, quote, sentence, interrogativeStack, qualifierStack);
                } break;
                default : {
                    throw new Error("Unhandled interrogative type! " + interrogativeStack.interrogative.toLowerCase());
                }
            }
        }
    }

}
