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

import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;

/**
 * <p>
 * this node comparison rule is capable of comparing selections. If both selections do not have
 * children, they are treated as lexically equal. If they have the same number of children other
 * than 0 and all these children are lexically equal, then the selections are lexically equal.
 * They are syntactically equal, if each child of both selections is syntactically equal to any
 * other child. The rule can not compare semantical equality if the nodes are not at least
 * syntactically equal and returns null, if it can not decide this.
 * </p>
 * 
 * @version $Revision: $ $Date: 19.02.2012$
 * @author 2012, last modified by $Author: patrick$
 */
public class SelectionComparisonRule implements NodeComparisonRule {

    /** the rule manager for internally comparing task tree nodes */
    private NodeEqualityRuleManager mRuleManager;

    /**
     * <p>
     * simple constructor to provide the rule with the node equality rule manager to be able
     * to perform comparisons of the children of provided task tree nodes
     * </p>
     * 
     * @param ruleManager the rule manager for comparing task tree nodes
     */
    SelectionComparisonRule(NodeEqualityRuleManager ruleManager) {
        super();
        mRuleManager = ruleManager;
    }

    /*
     * (non-Javadoc)
     * 
     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
     */
    @Override
    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
        if ((!(node1 instanceof ISelection)) || (!(node2 instanceof ISelection))) {
            return null;
        }

        // if both sequences do not have children, they are equal although this doesn't make sense
        if ((node1.getChildren().size() == 0) && (node2.getChildren().size() == 0)) {
            return NodeEquality.LEXICALLY_EQUAL;
        }

        // Selections are syntactically equal, if they have children, which are all syntactically
        // equal.
        // They are lexically equals, if they have the same number and order of lexically equal
        // children
        boolean lexicallyEqual = node1.getChildren().size() == node2.getChildren().size();

        for (int i = 0; i < node1.getChildren().size(); i++) {
            ITaskTreeNode child1 = node1.getChildren().get(i);
            boolean foundLexicallyEqualChild = false;

            for (int j = 0; j < node2.getChildren().size(); j++) {
                ITaskTreeNode child2 = node2.getChildren().get(j);

                NodeEquality nodeEquality = mRuleManager.applyRules(child1, child2);

                if (!nodeEquality.isAtLeast(NodeEquality.SYNTACTICALLY_EQUAL)) {
                    return null;
                }
                else if (nodeEquality.isAtLeast(NodeEquality.LEXICALLY_EQUAL)) {
                    foundLexicallyEqualChild = true;
                }
            }

            // if we compare two children at the same position and if they are lexically equal
            // then it can be further expected, that the selections are lexically equal
            lexicallyEqual &= foundLexicallyEqualChild;
        }

        if (lexicallyEqual) {
            return NodeEquality.LEXICALLY_EQUAL;
        }
        else {
            return NodeEquality.SYNTACTICALLY_EQUAL;
        }
    }
}
