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

import de.ugoe.cs.quest.eventcore.IEventTarget;
import de.ugoe.cs.quest.eventcore.gui.MouseButtonDown;
import de.ugoe.cs.quest.eventcore.gui.MouseButtonInteraction;
import de.ugoe.cs.quest.eventcore.gui.MouseButtonUp;
import de.ugoe.cs.quest.eventcore.gui.MouseClick;
import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;

/**
 * TODO comment
 * 
 * @version $Revision: $ $Date: 18.03.2012$
 * @author 2012, last modified by $Author: patrick$
 */
public class DefaultMouseClickReductionRule implements TemporalRelationshipRule {

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
     * TaskTreeBuilder, TaskTreeNodeFactory)
     */
    @Override
    public RuleApplicationResult apply(ITaskTreeNode        parent,
                                       ITaskTreeBuilder     builder,
                                       ITaskTreeNodeFactory nodeFactory,
                                       boolean              finalize)
    {
        if (!(parent instanceof ISequence)) {
            return null;
        }

        RuleApplicationResult result = new RuleApplicationResult();

        int index = 0;
        while (index < parent.getChildren().size() - 2) // -2 because we don't need to go to the end
        {
            if (mouseClickSequenceFound(parent.getChildren().get(index),
                                        parent.getChildren().get(index + 1),
                                        parent.getChildren().get(index + 2)))
            {
                builder.removeChild((ISequence) parent, index);
                builder.removeChild((ISequence) parent, index);
                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
                return result;
            }
            else if
                ((parent.getChildren().get(index) instanceof ISequence) &&
                 (parent.getChildren().get(index).getChildren().size() == 2) &&
                 (mouseClickSequenceFound(parent.getChildren().get(index).getChildren().get(0),
                                          parent.getChildren().get(index).getChildren().get(1),
                                          parent.getChildren().get(index + 1))))
            {
                builder.removeChild((ISequence) parent, index);
                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
                return result;
            }

            index++;
        }

        return result;
    }

    /**
     * 
     */
    private boolean mouseClickSequenceFound(ITaskTreeNode mouseButtonDown,
                                            ITaskTreeNode mouseButtonUp,
                                            ITaskTreeNode mouseClick)
    {
        // check the first in a row of three for validity
        if (!(mouseButtonDown instanceof IEventTask)) {
            return false;
        }

        if (!(((IEventTask) mouseButtonDown).getEventType() instanceof MouseButtonDown)) {
            return false;
        }

        // check the second node for validity
        if (!(mouseButtonUp instanceof IEventTask)) {
            return false;
        }

        IEventTarget eventTarget = ((IEventTask) mouseButtonDown).getEventTarget();

        if (!eventTarget.equals(((IEventTask) mouseButtonUp).getEventTarget())) {
            return false;
        }

        if (!(((IEventTask) mouseButtonUp).getEventType() instanceof MouseButtonUp)) {
            return false;
        }

        MouseButtonInteraction.Button button =
                ((MouseButtonDown) ((IEventTask) mouseButtonDown).getEventType()).getButton();

        if (!button.equals(((MouseButtonUp) ((IEventTask) mouseButtonUp).getEventType())
            .getButton()))
        {
            return false;
        }

        // check the third node for validity
        if (!(mouseClick instanceof IEventTask)) {
            return false;
        }

        if (!eventTarget.equals(((IEventTask) mouseClick).getEventTarget())) {
            return false;
        }

        if (!(((IEventTask) mouseClick).getEventType() instanceof MouseClick)) {
            return false;
        }

        if (!button.equals(((MouseClick) ((IEventTask) mouseClick).getEventType()).getButton())) {
            return false;
        }

        return true;
    }

}
