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

import de.ugoe.cs.quest.eventcore.IEventTarget;
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 DefaultEventTargetSequenceDetectionRule 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();

        IEventTarget currentEventTarget = null;
        int startingIndex = -1;

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

            IEventTarget eventTarget = determineEventTarget(child);

            if (((eventTarget == null) && (currentEventTarget != null)) ||
                ((eventTarget != null) && (!eventTarget.equals(currentEventTarget))))
            {
                if (startingIndex < 0) {
                    startingIndex = index;
                    currentEventTarget = eventTarget;
                }
                else {
                    handleEventTargetSequence(parent, startingIndex, index - 1, builder,
                                              nodeFactory, result);

                    return result;
                }
            }

            index++;
        }

        if (startingIndex > -1) {
            if (finalize && (startingIndex > 0)) {
                handleEventTargetSequence(parent, startingIndex, parent.getChildren().size() - 1,
                                          builder, nodeFactory, result);
            }
            else {
                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
            }
        }

        return result;
    }

    /**
     * TODO: comment
     * 
     * @param child
     * @return
     */
    private IEventTarget determineEventTarget(ITaskTreeNode node) {
        if (node instanceof IEventTask) {
            return ((IEventTask) node).getEventTarget();
        }
        else {
            return null;
        }
    }

    /**
     * TODO: comment
     * 
     */
    private void handleEventTargetSequence(ITaskTreeNode         parent,
                                           int                   startIndex,
                                           int                   endIndex,
                                           ITaskTreeBuilder      builder,
                                           ITaskTreeNodeFactory  nodeFactory,
                                           RuleApplicationResult result)
    {
        ISequence sequence = nodeFactory.createNewSequence();

        for (int i = startIndex; i <= endIndex; i++) {
            builder.addChild(sequence, parent.getChildren().get(startIndex));
            builder.removeChild((ISequence) parent, startIndex);
        }

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

        result.addNewlyCreatedParentNode(sequence);
        result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
    }

}
