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

import de.ugoe.cs.quest.tasktrees.treeifc.Iteration;
import de.ugoe.cs.quest.tasktrees.treeifc.Selection;
import de.ugoe.cs.quest.tasktrees.treeifc.TaskTreeNode;

//-------------------------------------------------------------------------------------------------
/**
 * TODO comment
 * 
 * @version $Revision: $ $Date: 19.02.2012$
 * @author 2012, last modified by $Author: patrick$
 */
//-------------------------------------------------------------------------------------------------
public class IterationComparisonRule implements NodeComparisonRule
{
  /** */
  private NodeEqualityRuleManager mRuleManager;

  //-----------------------------------------------------------------------------------------------
  /**
   * TODO: comment
   *
   */
  //-----------------------------------------------------------------------------------------------
  IterationComparisonRule(NodeEqualityRuleManager ruleManager)
  {
    super();
    mRuleManager = ruleManager;
  }

  //-----------------------------------------------------------------------------------------------
  /* (non-Javadoc)
   * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
   */
  //-----------------------------------------------------------------------------------------------
  @Override
  public NodeEquality compare(TaskTreeNode node1, TaskTreeNode node2)
  {
    if ((!(node1 instanceof Iteration)) || (!(node2 instanceof Iteration)))
    {
      return null;
    }
    
    // if both iterations do not have children, they are equal although this doesn't make sense
    if ((node1.getChildren().size() == 0) && (node2.getChildren().size() == 0))
    {
      return new NodesIdentical();
    }
    
    TaskTreeNode child1 = node1.getChildren().get(0);
    TaskTreeNode child2 = node2.getChildren().get(0);
    
    // iterations may have 3 different structures.
    //   1. they have one child, which is the iterated one
    //   2. they have a sequence of children, which is iterated
    //   3. they have a selection of different iterated variants (usually the variants are
    //      semantically equal)
    //
    // the permutations of the three variants in combination must be checked
    
    // check if both nodes are the same variants of iterations and if their children are equal.
    // This condition matches, if both iterations are the same variants of iteration. I.e. three
    // combinations of the permutation are handled herewith.
    NodeEquality nodeEquality = mRuleManager.applyRules(child1, child2);
      
    if (nodeEquality.getStructuralEquality() || nodeEquality.getSemanticalEquality())
    {
      return nodeEquality;
    }
    
    // compare one iteration with a single node as a child and another one with a selection of
    // semantically equal nodes
    if (selectionChildrenSemanticallyEqualNode(child1, child2))
    {
      return new NodesSemanticallyEqual();
    }

    // all other combinations (i.e. sequence with single child and sequence with selection)
    // can not match
    return null;
  }

  //-----------------------------------------------------------------------------------------------
  /**
   * TODO: comment
   *
   * @param taskTreeNode
   * @param taskTreeNode2
   * @return
   */
  //-----------------------------------------------------------------------------------------------
  private boolean selectionChildrenSemanticallyEqualNode(TaskTreeNode taskTreeNode,
                                                         TaskTreeNode taskTreeNode2)
  {
    Selection selection = null;
    TaskTreeNode node = null;
    if (taskTreeNode instanceof Selection)
    {
      selection = (Selection) taskTreeNode;
      node = taskTreeNode2;
    }
    else if (taskTreeNode2 instanceof Selection)
    {
      selection = (Selection) taskTreeNode2;
      node = taskTreeNode;
    }
    else
    {
      return false;
    }
    
    for (TaskTreeNode child : selection.getChildren())
    {
      NodeEquality nodeEquality = mRuleManager.applyRules(node, child);
          
      if (!nodeEquality.getStructuralEquality() && !nodeEquality.getSemanticalEquality())
      {
        return false;
      }
    }
    
    return true;
  }

}
