package de.ugoe.cs.quest.tasktrees.nodeequality;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import de.ugoe.cs.quest.eventcore.Event;
import de.ugoe.cs.quest.eventcore.IEventTarget;
import de.ugoe.cs.quest.eventcore.IEventType;
import de.ugoe.cs.quest.eventcore.StringEventType;
import de.ugoe.cs.quest.eventcore.gui.KeyboardFocusChange;
import de.ugoe.cs.quest.eventcore.gui.TextInput;
import de.ugoe.cs.quest.eventcore.gui.ValueSelection;
import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
import de.ugoe.cs.quest.tasktrees.treeimpl.TaskTreeNodeFactory;
import de.ugoe.cs.quest.test.DummyGUIElement;

/**
 * @author Patrick Harms
 */
public class GUIEventTaskComparisonRuleTest {

    /**
     *
     */
    @Test
    public void test() {
        ITaskTreeNodeFactory treeNodeFactory = new TaskTreeNodeFactory();
        
        GUIEventTaskComparisonRule rule = new GUIEventTaskComparisonRule();
        
        // test the identity check
        IEventType eventType1 = new StringEventType("blub");
        IEventTarget eventTarget1 = new DummyGUIElement("elem1");
        ITaskTreeNode task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        
        assertNull(rule.compare(task1, task1));

        eventType1 = new KeyboardFocusChange();
        task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        
        assertEquals(NodeEquality.IDENTICAL, rule.compare(task1, task1));

        // test lexical equality for interaction events which are no value selections or text inputs
        IEventType eventType2 = new KeyboardFocusChange();
        ITaskTreeNode task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget1);
        
        assertEquals(NodeEquality.LEXICALLY_EQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.LEXICALLY_EQUAL, rule.compare(task2, task1));
        
        // test equality of value selections
        eventType1 = new ValueSelection<String>("value1");
        task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task2, task1));
        
        eventType2 = new ValueSelection<String>("value1");
        task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget1);
        
        assertEquals(NodeEquality.SYNTACTICALLY_EQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.SYNTACTICALLY_EQUAL, rule.compare(task2, task1));
        
        eventType2 = new ValueSelection<String>("value2");
        task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget1);
        
        assertEquals(NodeEquality.SEMANTICALLY_EQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.SEMANTICALLY_EQUAL, rule.compare(task2, task1));
        
        // test equality of text inputs
        List<Event> textInputEvents1 = new ArrayList<Event>();
        textInputEvents1.add(new Event(eventType1, eventTarget1));
        eventType1 = new TextInput("enteredText1", textInputEvents1);
        task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task2, task1));
        
        eventType2 = new TextInput("enteredText1", textInputEvents1);
        task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget1);
        
        assertEquals(NodeEquality.LEXICALLY_EQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.LEXICALLY_EQUAL, rule.compare(task2, task1));
        
        List<Event> textInputEvents2 = new ArrayList<Event>();
        textInputEvents2.add(new Event(eventType2, eventTarget1));
        eventType2 = new TextInput("enteredText1", textInputEvents2);
        task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget1);
        
        assertEquals(NodeEquality.SYNTACTICALLY_EQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.SYNTACTICALLY_EQUAL, rule.compare(task2, task1));
        
        eventType2 = new TextInput("enteredText2", textInputEvents2);
        task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget1);
        
        assertEquals(NodeEquality.SEMANTICALLY_EQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.SEMANTICALLY_EQUAL, rule.compare(task2, task1));
        
        // now ensure unequality for all combinations, if the event targets do not match
        IEventTarget eventTarget2 = new DummyGUIElement("elem2");
        eventType1 = new KeyboardFocusChange();
        task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        task2 = treeNodeFactory.createNewEventTask(eventType2, eventTarget2);
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task2, task1));
        
        eventType1 = new ValueSelection<String>("value1");
        task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        task2 = treeNodeFactory.createNewEventTask(eventType1, eventTarget2);
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task2, task1));
        
        eventType1 = new TextInput("enteredText1", textInputEvents1);
        task1 = treeNodeFactory.createNewEventTask(eventType1, eventTarget1);
        task2 = treeNodeFactory.createNewEventTask(eventType1, eventTarget2);
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task1, task2));
        assertEquals(NodeEquality.UNEQUAL, rule.compare(task2, task1));

        ISelection selection = treeNodeFactory.createNewSelection();
        assertNull(rule.compare(task1, selection));
        assertNull(rule.compare(selection, task1));
        assertNull(rule.compare(task2, selection));
        assertNull(rule.compare(selection, task2));
    }

}
