package edu.cmu.chimps.messageontap_api;


import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

/**
 * This is the data type for plugins to set up their triggers at message perception
 * 1. Tag List
 *
 */

/**
 *     Trigger

 + Set<Tag> mandatoryTags

 + Set<Tag> optionalTags

 + Set<Constraint> contraints

 + int mood

 + int direction

 */
public class Trigger {


    private static final int ROOT_PARENT_ID = -1;

    public boolean isConcatenation(ParseTree parseTree, ParseTree.Node a, ParseTree.Node b){
        //TODO : ROOT NODE
        if(a.getParentId() == ROOT_PARENT_ID){
            return false;
        }
        else{
            if(parseTree.mNodeList.get(a.getParentId()).getChildrenIds().contains(b.getId())){
                return true;
            }
        }
        return true;
    }

    public boolean isSubordinate(ParseTree.Node a, ParseTree.Node b){
        //TODO : ROOT NODE
        if(a.getChildrenIds() == null){
            return false;
        }
        else{
            if(a.getChildrenIds().contains(b.getId())){
                return true;
            }
        }
        return true;
    }

    enum Mood{MOOD_UNKNOWN, MOOD_IMPERATIVE, MOOD_INTERROGTIVE}
    enum Relation{UNKNOWN, CONCATENATION, SUBORDINATE}
    enum Direction {UNKNOWN_DIRECTION, INCOMING_DIRECTION, OUTGOING_DIRECTION}

    private class Constraint{
        //TODO
        String tagA_name = "";
        String tagB_name = "";
        Relation relation = Relation.UNKNOWN;
    }

    private String name = "null";

    private Set<String> mMadatoryTags = new HashSet<>();

    private Set<String> mOptionalTags = new HashSet<>();

    private Set<Constraint> mConstraints = new HashSet<>();

    private Mood mMood = Mood.MOOD_UNKNOWN;

    private Direction mDirection = Direction.UNKNOWN_DIRECTION;

    private String mPackageName; //TODO: Plugin Id

    public Trigger() {
        name = "";
        mMadatoryTags = new HashSet<String>();
        mOptionalTags = new HashSet<String>();
        mConstraints = new HashSet<Constraint>();
        mMood = Mood.MOOD_UNKNOWN;
        mDirection = Direction.UNKNOWN_DIRECTION;
    }

    public Trigger(String name, Set<Tag> pluginMadatoryTags) {
        this.name = name;
        for(Tag t:pluginMadatoryTags) {
            mMadatoryTags.add(t.getName());
        }
    }

    public Trigger(String name, Set<Tag> pluginMadatoryTags, Set<Tag> pluginOptionalTags) {
        this.name = name;
        for(Tag t:pluginMadatoryTags) {
            mMadatoryTags.add(t.getName());

        }
        for(Tag t:pluginOptionalTags) {
            mOptionalTags.add(t.getName());

        }
    }

    public Trigger(String name, Set<Tag> pluginMadatoryTags, Set<Tag> pluginOptionalTags, Set<Constraint> constraints){
        this.name = name;
        for(Tag t:pluginMadatoryTags) {
            mMadatoryTags.add(t.getName());

        }
        for(Tag t:pluginOptionalTags) {
            mOptionalTags.add(t.getName());

        }
        this.mConstraints = constraints;
    }

    public Trigger(String name, Set<Tag> pluginMadatoryTags, Set<Tag> pluginOptionalTags, Set<Constraint> constraints
                    , Mood mood, Direction direction){
        this.name = name;
        for(Tag t:pluginMadatoryTags) {
            mMadatoryTags.add(t.getName());

        }
        for(Tag t:pluginOptionalTags) {
            mOptionalTags.add(t.getName());

        }
        if(constraints != null)
            this.mConstraints = constraints;
        this.mMood = mood;
        this.mDirection = direction;
    }

    public String getPackageName() {
        return mPackageName;
    }

    public void setPackageName(String packageName) {
        mPackageName = packageName;
    }

    public String getJson() {
        return DataUtils.SimpleObjectToJson(this, Globals.TYPE_TRIGGER);
    }

    public String getTypeKey() {
        return Globals.TYPE_TRIGGER;
    }

    public boolean matchTrigger(ParseTree parseTree){
        // 1. Tag List
        // 2. Tag Relation
        // 3. Mood? Direction?

        boolean flag = false;
        //Direction Judge
        //Incoming or Outgoing?
        if(mDirection != Direction.UNKNOWN_DIRECTION) {
            if (parseTree.direction != mDirection) {
                return false;
            }
        }

        //Mood Judge
        //IMPERATIVE, INTERROGTIVE
        if(mMood != Mood.MOOD_UNKNOWN) {
            if (parseTree.mood != mMood) {
                return false;
            }
        }

        //Tag Judge Contains

        //Add Tags from ParseTree
        HashMap<String, Integer> tagNames = new HashMap<>();
        for (int i = 0; i < parseTree.mNodeList.size(); i++) {
            if (!parseTree.mNodeList.get(i).getTagList().isEmpty()) {
                for (Tag t : parseTree.mNodeList.get(i).getTagList()) {
                    tagNames.put(t.getName(), i);
                }
            }
        }

        if(!mMadatoryTags.isEmpty()) {
            if(!tagNames.keySet().contains(mMadatoryTags)){
                return false;
            }
        }

        //A -> B
        if(!mConstraints.isEmpty()){
            for(Constraint c:mConstraints){
                String tagA = c.tagA_name;
                String tagB = c.tagB_name;
                Relation relation = c.relation;
                ParseTree.Node nodeA = parseTree.mNodeList.get(tagNames.get(tagA));
                ParseTree.Node nodeB = parseTree.mNodeList.get(tagNames.get(tagB));
                if(relation == Relation.CONCATENATION){
                    if(!isConcatenation(parseTree, nodeA, nodeB)){
                        return false;
                    }
                }
                if(relation == Relation.SUBORDINATE){
                    if(!isSubordinate(nodeA, nodeB)){
                        return false;
                    }
                }

            }
        }

        return true;
    }

}

@@ -1167,195 +1167,52 @@
 num 
-Mood%7BMOOD_UNKNOWN, MOOD_IMPERATIVE, MOOD_INTERROGTIVE%7D%0A    enum Relation%7BUNKNOWN, CONCATENATION, SUBORDINATE%7D%0A    enum Direction %7BUNKNOWN_DIRECTION, INCOMING_DIRECTION, OUTGOING_DIRECTION
+Relation%7BUNKNOWN, CONCATENATION, SUBORDINATE
 %7D%0A%0A 
@@ -1594,16 +1594,26 @@
 private 
+ParseTree.
 Mood mMo
@@ -1609,32 +1609,42 @@
 ee.Mood mMood = 
+ParseTree.
 Mood.MOOD_UNKNOW
@@ -1659,16 +1659,26 @@
 private 
+ParseTree.
 Directio
@@ -1684,32 +1684,42 @@
 on mDirection = 
+ParseTree.
 Direction.UNKNOW
@@ -1986,16 +1986,26 @@
 mMood = 
+ParseTree.
 Mood.MOO
@@ -2036,16 +2036,26 @@
 ction = 
+ParseTree.
 Directio
@@ -3111,16 +3111,26 @@
       , 
+ParseTree.
 Mood moo
@@ -3132,16 +3132,26 @@
 d mood, 
+ParseTree.
 Directio
@@ -4133,16 +4133,26 @@
 tion != 
+ParseTree.
 Directio
@@ -4358,16 +4358,26 @@
 Mood != 
+ParseTree.
 Mood.MOO

fix error