//-------------------------------------------------------------------------------------------------
// Module    : $RCSfile: DefaultSequenceDetectionRule.java,v $
// Version   : $Revision: 0.0 $  $Author: patrick $  $Date: 18.03.2012 $
// Project   : TaskTreeCreator
// Creation  : 2012 by patrick
// Copyright : Patrick Harms, 2012
//-------------------------------------------------------------------------------------------------
package de.ugoe.cs.quest.tasktrees.temporalrelation;

import de.ugoe.cs.quest.tasktrees.treeifc.InteractionTask;
import de.ugoe.cs.quest.tasktrees.treeifc.Sequence;
import de.ugoe.cs.quest.tasktrees.treeifc.TaskTreeBuilder;
import de.ugoe.cs.quest.tasktrees.treeifc.TaskTreeNode;
import de.ugoe.cs.quest.tasktrees.treeifc.TaskTreeNodeFactory;

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

  //-----------------------------------------------------------------------------------------------
  /* (non-Javadoc)
   * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode, TaskTreeBuilder, TaskTreeNodeFactory)
   */
  //-----------------------------------------------------------------------------------------------
  @Override
  public RuleApplicationResult apply(TaskTreeNode        parent,
                                     TaskTreeBuilder     builder,
                                     TaskTreeNodeFactory nodeFactory,
                                     boolean             finalize)
  {
    if (!(parent instanceof Sequence))
    {
      return null;
    }
    
    RuleApplicationResult result = new RuleApplicationResult();
    int sequenceStartingIndex = -1;
    
    int index = 0;
    while (index < parent.getChildren().size())
    {
      TaskTreeNode child = parent.getChildren().get(index);
      
      if (child instanceof InteractionTask)
      {
        if (((InteractionTask) child).getInteraction().finishesLogicalSequence() &&
            (sequenceStartingIndex > -1))
        {
          // There are several situations in which this implementation may cause infinite
          // loops. This is because the rule manager will reapply rules until
          // no rule is applied anymore. A sequence identified in a first iteration will
          // be identified as a sequence also in a second iteration. As an example
          // many sequences start with an interaction starting that sequence and end
          // with an interaction ending that sequence. This will be reidentified as further 
          // subsequence. It must therefore be assured, that a sequence, that was once
          // identified is not reidentified in a further application of the rule. For this,
          // the implementation performs a kind of dry run. It creates a list of children
          // that would belong to an identified sequence. Only if this list is not a
          // reidentification then a new sequence is created and added to the parent. If it
          // is a reidentification can be identified, if the list of children will contain
          // all children of the parent, or if the list of children only consists of one
          // sequence. Further, an identified sequence must at least have one child.
          if (((sequenceStartingIndex != 0) || (index != (parent.getChildren().size() - 1))) &&
              (((index - sequenceStartingIndex) > 0) ||
                (((index - sequenceStartingIndex) == 0) &&
                 (!((InteractionTask) child).getInteraction().startsLogicalSequence()))))
          {
            boolean allNewChildrenAreSequences = true;
            
            for (int j = sequenceStartingIndex; ((allNewChildrenAreSequences) && (j < index)); j++)
            {
              allNewChildrenAreSequences &= (parent.getChildren().get(j) instanceof Sequence);
            }
            
            if (!allNewChildrenAreSequences)
            {
              Sequence sequence = nodeFactory.createNewSequence();
            
              for (int j = sequenceStartingIndex; j < index; j++)
              {
                builder.addChild(sequence, parent.getChildren().get(sequenceStartingIndex));
                builder.removeChild((Sequence) parent, sequenceStartingIndex);
              }

              if (!((InteractionTask) child).getInteraction().startsLogicalSequence())
              {
                builder.addChild(sequence, parent.getChildren().get(sequenceStartingIndex));
                builder.removeChild((Sequence) parent, sequenceStartingIndex);
              }

              builder.addChild((Sequence) parent, sequenceStartingIndex, sequence);

              result.addNewlyCreatedParentNode(sequence);
              result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
              return result;
            }
          }
        }
        
        if (((InteractionTask) child).getInteraction().startsLogicalSequence())
        {
          sequenceStartingIndex = index;
        }
      }
      
      index++;
    }
    
    if (sequenceStartingIndex >= 0)
    {
      result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
    }
    
    return result;
  }

}
