//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package de.ugoe.cs.autoquest.tasktrees.taskequality;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.autoquest.eventcore.IEventTarget;
import de.ugoe.cs.autoquest.eventcore.IEventType;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
import de.ugoe.cs.autoquest.tasktrees.treeimpl.TaskBuilder;
import de.ugoe.cs.autoquest.tasktrees.treeimpl.TaskFactory;

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

    /** */
    private ITaskFactory taskFactory = new TaskFactory();

    /** */
    private ITaskBuilder taskBuilder = new TaskBuilder();

    /**
     *
     */
    protected IEventTask createNewEventTask(IEventType eventType, IEventTarget eventTarget) {
        IEventTask eventTask = taskFactory.createNewEventTask(eventType + " --> " + eventTarget);
        taskFactory.createNewTaskInstance(eventTask, new Event(eventType, eventTarget));
        return eventTask;
    }

    /**
     *
     */
    protected ISequence createNewSequence() {
        ISequence sequence = taskFactory.createNewSequence();
        taskFactory.createNewTaskInstance(sequence);
        return sequence;
    }

    /**
     *
     */
    protected ISelection createNewSelection() {
        ISelection selection = taskFactory.createNewSelection();
        taskFactory.createNewTaskInstance(selection);
        return selection;
    }

    /**
     *
     */
    protected IOptional createNewOptional() {
        IOptional optional = taskFactory.createNewOptional();
        taskFactory.createNewTaskInstance(optional);
        return optional;
    }

    /**
     *
     */
    protected IIteration createNewIteration() {
        IIteration iteration = taskFactory.createNewIteration();
        taskFactory.createNewTaskInstance(iteration);
        return iteration;
    }
    
    /**
     *
     */
    protected void setMarkedTask(IIteration iteration, ITask task) {
        taskBuilder.setMarkedTask(iteration, task);
        taskBuilder.addChild((IIterationInstance) iteration.getInstances().iterator().next(),
                             task.getInstances().iterator().next());
    }

    /**
     *
     */
    protected void addChild(ISelection selection, ITask task) {
        taskBuilder.addChild(selection, task);
        taskBuilder.setChild((ISelectionInstance) selection.getInstances().iterator().next(),
                             task.getInstances().iterator().next());
    }

    /**
     *
     */
    protected void addChild(ISequence sequence, ITask task) {
        taskBuilder.addChild(sequence, task);
        taskBuilder.addChild((ISequenceInstance) sequence.getInstances().iterator().next(),
                             task.getInstances().iterator().next());
    }

    /**
     *
     */
    protected void assertLexicallyEqual(TaskComparisonRule rule, ITask task1, ITask task2) {
        assertEquals(TaskEquality.LEXICALLY_EQUAL, rule.compare(task1, task2));
        assertTrue(rule.areLexicallyEqual(task1, task2));
        assertTrue(rule.areSyntacticallyEqual(task1, task2));
        assertTrue(rule.areSemanticallyEqual(task1, task2));

        assertEquals(TaskEquality.LEXICALLY_EQUAL, rule.compare(task2, task1));
        assertTrue(rule.areLexicallyEqual(task2, task1));
        assertTrue(rule.areSyntacticallyEqual(task2, task1));
        assertTrue(rule.areSemanticallyEqual(task2, task1));
        
        assertEquals(TaskEquality.LEXICALLY_EQUAL,
                     rule.compare(task1.getInstances().iterator().next(),
                                  task2.getInstances().iterator().next()));
        assertTrue(rule.areLexicallyEqual(task1.getInstances().iterator().next(),
                                          task2.getInstances().iterator().next()));
        assertTrue(rule.areSyntacticallyEqual(task1.getInstances().iterator().next(),
                                              task2.getInstances().iterator().next()));
        assertTrue(rule.areSemanticallyEqual(task1.getInstances().iterator().next(),
                                             task2.getInstances().iterator().next()));

        assertEquals(TaskEquality.LEXICALLY_EQUAL,
                     rule.compare(task2.getInstances().iterator().next(),
                                  task1.getInstances().iterator().next()));
        assertTrue(rule.areLexicallyEqual(task2.getInstances().iterator().next(),
                                          task1.getInstances().iterator().next()));
        assertTrue(rule.areSyntacticallyEqual(task2.getInstances().iterator().next(),
                                              task1.getInstances().iterator().next()));
        assertTrue(rule.areSemanticallyEqual(task2.getInstances().iterator().next(),
                                             task1.getInstances().iterator().next()));
    }

    /**
     *
     */
    protected void assertSyntacticallyEqual(TaskComparisonRule rule, ITask task1, ITask task2) {
        assertEquals(TaskEquality.SYNTACTICALLY_EQUAL, rule.compare(task1, task2));
        assertFalse(rule.areLexicallyEqual(task1, task2));
        assertTrue(rule.areSyntacticallyEqual(task1, task2));
        assertTrue(rule.areSemanticallyEqual(task1, task2));

        assertEquals(TaskEquality.SYNTACTICALLY_EQUAL, rule.compare(task2, task1));
        assertFalse(rule.areLexicallyEqual(task2, task1));
        assertTrue(rule.areSyntacticallyEqual(task2, task1));
        assertTrue(rule.areSemanticallyEqual(task2, task1));
        
        assertEquals(TaskEquality.SYNTACTICALLY_EQUAL,
                     rule.compare(task1.getInstances().iterator().next(),
                                  task2.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task1.getInstances().iterator().next(),
                                           task2.getInstances().iterator().next()));
        assertTrue(rule.areSyntacticallyEqual(task1.getInstances().iterator().next(),
                                              task2.getInstances().iterator().next()));
        assertTrue(rule.areSemanticallyEqual(task1.getInstances().iterator().next(),
                                             task2.getInstances().iterator().next()));

        assertEquals(TaskEquality.SYNTACTICALLY_EQUAL,
                     rule.compare(task2.getInstances().iterator().next(),
                                  task1.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task2.getInstances().iterator().next(),
                                           task1.getInstances().iterator().next()));
        assertTrue(rule.areSyntacticallyEqual(task2.getInstances().iterator().next(),
                                              task1.getInstances().iterator().next()));
        assertTrue(rule.areSemanticallyEqual(task2.getInstances().iterator().next(),
                                             task1.getInstances().iterator().next()));
    }

    /**
     *
     */
    protected void assertSemanticallyEqual(TaskComparisonRule rule, ITask task1, ITask task2) {
        assertEquals(TaskEquality.SEMANTICALLY_EQUAL, rule.compare(task1, task2));
        assertFalse(rule.areLexicallyEqual(task1, task2));
        assertFalse(rule.areSyntacticallyEqual(task1, task2));
        assertTrue(rule.areSemanticallyEqual(task1, task2));

        assertEquals(TaskEquality.SEMANTICALLY_EQUAL, rule.compare(task2, task1));
        assertFalse(rule.areLexicallyEqual(task2, task1));
        assertFalse(rule.areSyntacticallyEqual(task2, task1));
        assertTrue(rule.areSemanticallyEqual(task2, task1));
        
        assertEquals(TaskEquality.SEMANTICALLY_EQUAL,
                     rule.compare(task1.getInstances().iterator().next(),
                                  task2.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task1.getInstances().iterator().next(),
                                           task2.getInstances().iterator().next()));
        assertFalse(rule.areSyntacticallyEqual(task1.getInstances().iterator().next(),
                                               task2.getInstances().iterator().next()));
        assertTrue(rule.areSemanticallyEqual(task1.getInstances().iterator().next(),
                                             task2.getInstances().iterator().next()));

        assertEquals(TaskEquality.SEMANTICALLY_EQUAL,
                     rule.compare(task2.getInstances().iterator().next(),
                                  task1.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task2.getInstances().iterator().next(),
                                           task1.getInstances().iterator().next()));
        assertFalse(rule.areSyntacticallyEqual(task2.getInstances().iterator().next(),
                                               task1.getInstances().iterator().next()));
        assertTrue(rule.areSemanticallyEqual(task2.getInstances().iterator().next(),
                                             task1.getInstances().iterator().next()));
    }

    /**
     *
     */
    protected void assertUnequal(TaskComparisonRule rule, ITask task1, ITask task2) {
        assertEquals(TaskEquality.UNEQUAL, rule.compare(task1, task2));
        assertFalse(rule.areLexicallyEqual(task1, task2));
        assertFalse(rule.areSyntacticallyEqual(task1, task2));
        assertFalse(rule.areSemanticallyEqual(task1, task2));

        assertEquals(TaskEquality.UNEQUAL, rule.compare(task2, task1));
        assertFalse(rule.areLexicallyEqual(task2, task1));
        assertFalse(rule.areSyntacticallyEqual(task2, task1));
        assertFalse(rule.areSemanticallyEqual(task2, task1));
        
        assertEquals(TaskEquality.UNEQUAL,
                     rule.compare(task1.getInstances().iterator().next(),
                                  task2.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task1.getInstances().iterator().next(),
                                           task2.getInstances().iterator().next()));
        assertFalse(rule.areSyntacticallyEqual(task1.getInstances().iterator().next(),
                                               task2.getInstances().iterator().next()));
        assertFalse(rule.areSemanticallyEqual(task1.getInstances().iterator().next(),
                                              task2.getInstances().iterator().next()));

        assertEquals(TaskEquality.UNEQUAL,
                     rule.compare(task2.getInstances().iterator().next(),
                                  task1.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task2.getInstances().iterator().next(),
                                           task1.getInstances().iterator().next()));
        assertFalse(rule.areSyntacticallyEqual(task2.getInstances().iterator().next(),
                                               task1.getInstances().iterator().next()));
        assertFalse(rule.areSemanticallyEqual(task2.getInstances().iterator().next(),
                                              task1.getInstances().iterator().next()));
    }

    /**
     *
     */
    protected void assertNullEquality(TaskComparisonRule rule, ITask task1, ITask task2) {
        assertNull(rule.compare(task1, task2));
        assertFalse(rule.areLexicallyEqual(task1, task2));
        assertFalse(rule.areSyntacticallyEqual(task1, task2));
        assertFalse(rule.areSemanticallyEqual(task1, task2));

        assertNull(rule.compare(task2, task1));
        assertFalse(rule.areLexicallyEqual(task2, task1));
        assertFalse(rule.areSyntacticallyEqual(task2, task1));
        assertFalse(rule.areSemanticallyEqual(task2, task1));
        
        assertNull(rule.compare(task1.getInstances().iterator().next(),
                                task2.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task1.getInstances().iterator().next(),
                                           task2.getInstances().iterator().next()));
        assertFalse(rule.areSyntacticallyEqual(task1.getInstances().iterator().next(),
                                               task2.getInstances().iterator().next()));
        assertFalse(rule.areSemanticallyEqual(task1.getInstances().iterator().next(),
                                              task2.getInstances().iterator().next()));

        assertNull(rule.compare(task2.getInstances().iterator().next(),
                                task1.getInstances().iterator().next()));
        assertFalse(rule.areLexicallyEqual(task2.getInstances().iterator().next(),
                                           task1.getInstances().iterator().next()));
        assertFalse(rule.areSyntacticallyEqual(task2.getInstances().iterator().next(),
                                               task1.getInstances().iterator().next()));
        assertFalse(rule.areSemanticallyEqual(task2.getInstances().iterator().next(),
                                              task1.getInstances().iterator().next()));
    }
}
