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

import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection;
import de.ugoe.cs.autoquest.eventcore.guimodel.ITrackBar;
import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality;
import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory;

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

    /** */
    private NodeEqualityRuleManager nodeEqualityRuleManager;

    /**
     * TODO: comment
     * 
     */
    TrackBarSelectionDetectionRule(NodeEqualityRuleManager nodeEqualityRuleManager) {
        super();
        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
    }

    /*
     * (non-Javadoc)
     * 
     * @see 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 valueSelectionStartIndex = -1;

        int index = 0;
        while (index < parent.getChildren().size()) {
            ITaskTreeNode child = parent.getChildren().get(index);

            if ((child instanceof IEventTask) &&
                (((IEventTask) child).getEventTarget() instanceof ITrackBar) &&
                (((IEventTask) child).getEventType() instanceof ValueSelection))
            {
                if (valueSelectionStartIndex < 0) {
                    // let the show begin
                    valueSelectionStartIndex = index;
                }
            }
            else if (valueSelectionStartIndex >= 0) {
                // current child is no more value selection. But the preceding tasks were.
                // Therefore,
                // create an iteration with the different selectable values as selection children
                handleValueSelections(valueSelectionStartIndex, index - 1, parent, builder,
                                      nodeFactory, result);

                return result;
            }

            index++;
        }

        if (valueSelectionStartIndex >= 0) {
            if (finalize) {
                handleValueSelections(valueSelectionStartIndex, parent.getChildren().size() - 1,
                                      parent, builder, nodeFactory, result);
            }
            else {
                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
            }
        }

        return result;
    }

    /**
     * TODO: comment
     * 
     * @param valueSelectionStartIndex
     * @param i
     */
    private void handleValueSelections(int                   startIndex,
                                       int                   endIndex,
                                       ITaskTreeNode         parent,
                                       ITaskTreeBuilder      builder,
                                       ITaskTreeNodeFactory  nodeFactory,
                                       RuleApplicationResult result)
    {
        IIteration iteration = nodeFactory.createNewIteration();
        result.addNewlyCreatedParentNode(iteration);

        ISelection selection = nodeFactory.createNewSelection();
        result.addNewlyCreatedParentNode(selection);
        builder.setChild(iteration, selection);

        for (int i = endIndex - startIndex; i >= 0; i--) {
            addChildIfNecessary(selection, parent.getChildren().get(startIndex), builder,
                                nodeFactory, result);
            builder.removeChild((ISequence) parent, startIndex);
        }

        builder.addChild((ISequence) parent, startIndex, iteration);

        result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
    }

    /**
     *
     */
    private void addChildIfNecessary(ISelection            parentSelection,
                                     ITaskTreeNode         node,
                                     ITaskTreeBuilder      builder,
                                     ITaskTreeNodeFactory  nodeFactory,
                                     RuleApplicationResult result)
    {
        for (int i = 0; i < parentSelection.getChildren().size(); i++) {
            ITaskTreeNode child = parentSelection.getChildren().get(i);

            // check, if the new node is a variant for the current event task
            NodeEquality nodeEquality = nodeEqualityRuleManager.applyRules(child, node);
            if (nodeEquality.isAtLeast(NodeEquality.SYNTACTICALLY_EQUAL)) {
                return;
            }
        }

        // if we did not return in the previous checks, then the node must be added
        builder.addChild(parentSelection, node);
    }

}
