package org.studiorailgun.ai.conversation.parser.depend;

import java.util.List;

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

/**
 * A linguistic argument
 */
public class Argument {
    
    /**
     * The type of a given argument
     */
    public static enum ArgumentType {

        /**
         * A noun or collection of words that functions as a noun
         */
        NOMINAL,

        /**
         * A subject of a dependent clause in a compound sentence
         */
        COMPOUND_MODIFIER,

        /**
         * A dependent clause that is functioning as an argument
         */
        CLAUSAL_COMPLEMENT,
    }

    /**
     * The type of this argument
     */
    ArgumentType type;

    /**
     * The root of the argument
     */
    IndexedWord root;

    /**
     * The possessive modifier being applied to the argument
     */
    IndexedWord possessiveModifier;

    /**
     * The determiner for the argument
     */
    IndexedWord determiner;

    /**
     * The preposition being applied to this argument
     */
    IndexedWord preposition;

    /**
     * The adjective modifying this argument
     */
    IndexedWord adjective;

    /**
     * The adverb modifying this argument
     */
    IndexedWord adverb;

    /**
     * Constructor
     * @param root The root of the argument
     */
    private Argument(IndexedWord root, ArgumentType type){
        this.root = root;
    }

    /**
     * Gets the root of this argument
     * @return The root
     */
    public IndexedWord getRoot(){
        return root;
    }

    /**
     * Parses an argument
     * @param graph The graph
     * @param root The root of the argument
     * @param type The type of the argument
     * @return The parsed argument
     */
    public static Argument parse(SemanticGraph graph, IndexedWord root, ArgumentType type){
        Argument rVal = new Argument(root, type);
        List<IndexedWord> children = graph.getChildList(root);
        //parse all arguments
        for(IndexedWord child : children){
            GrammaticalRelation relation = graph.reln(root, child);
            switch(relation.getLongName()){

                //possessive modifier
                case "possession modifier": {
                    rVal.possessiveModifier = child;
                } break;

                //determiner
                case "determiner": {
                    rVal.determiner = child;
                } break;

                //preposition
                case "nmod_preposition": {
                    rVal.preposition = child;
                } break;

                //adjective
                case "adjectival modifier": {
                    rVal.adjective = child;
                } break;

                //adverb
                case "adverbial modifier": {
                    rVal.adverb = child;
                } break;


                //this will have already been parsed at the clause level, want to ignore now
                case "advcl_preposition":
                //this will have already been parsed at the clause level, want to ignore now
                case "parataxis":
                //this will have already been parsed at the clause level, want to ignore now
                case "punctuation":
                //this will have already been parsed at the clause level, want to ignore now
                case "copula":
                //this can occur when we are parsing the root nominal of a non-verbal copular sentence -- we would expect the root to point at the subject of the copular and we don't want that subject to be a part of this argument
                case "nominal subject": {
                    //cases to ignore
                    continue;
                }

                //unhandled cases
                default: {
                    throw new Error("Unsupported relation type! " + relation.getLongName() + "\n" + "for " + child.originalText() + "\n" + graph);
                }
            }
        }
        return rVal;
    }

    /**
     * Gets the possessive modifier of this argument
     * @return The possessive modifier
     */
    public IndexedWord getPossessiveModifier(){
        return possessiveModifier;
    }

}
