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

import java.util.ArrayList;
import java.util.List;

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

/**
 * <p>
 * The node equality rule manager is capable of comparing task tree nodes based on its internal list
 * of comparison rules. The current list of rules contains the {@link NodeIdentityRule}, the
 * {@link IterationComparisonRule}, the {@link SequenceComparisonRule}, and
 * {@link SelectionComparisonRule}. These rules are asked for comparing the two provided task tree
 * nodes in the mentioned order. If a rule returns a node equality other than null, this equality is
 * returned. Otherwise the next rule is asked.
 * </p>
 * 
 * @version $Revision: $ $Date: 19.02.2012$
 * @author 2012, last modified by $Author: patrick$
 */
public class NodeEqualityRuleManager {

    /** */
    private List<NodeComparisonRule> mRuleIndex = null;

    /**
     * <p>
     * initializes the node equality rule manager by filling the internal list of comparison rules.
     * This method must be called before any other method is called on the rule manager.
     * </p>
     */
    public void init() {
        mRuleIndex = new ArrayList<NodeComparisonRule>();
        mRuleIndex.add(new NodeIdentityRule());
        mRuleIndex.add(new GUIEventTaskComparisonRule());
        mRuleIndex.add(new EventTaskComparisonRule());
        mRuleIndex.add(new IterationComparisonRule(this));
        mRuleIndex.add(new SequenceComparisonRule(this));
        mRuleIndex.add(new SelectionComparisonRule(this));
        mRuleIndex.add(new NodeAndIterationComparisonRule(this));
        mRuleIndex.add(new NodeAndSelectionComparisonRule(this));
    }

    /**
     * <p>
     * this method performs a comparison of the two provided task tree nodes. It iterates its
     * internal comparison rules. If the first rule returns a node equality other than null,
     * this equality is returned. Otherwise the next rule is tried. If no rule returns an equality
     * <code>NodeEquality.UNEQUAL</code> is returned.
     * </p>
     * 
     * @param node1 the first task tree node to be compared
     * @param node2 the second task tree node to be compared
     * 
     * @return as described
     * 
     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
     *                               manager before a call to this method.
     */
    public NodeEquality applyRules(ITaskTreeNode node1, ITaskTreeNode node2)
        throws IllegalStateException
    {
        if (mRuleIndex == null) {
            throw new IllegalStateException("not initialized");
        }
        
        // LOG.info("checking for equality of " + node1 + " and " + node2);
        NodeEquality nodeEquality = null;

        for (NodeComparisonRule rule : mRuleIndex) {
            nodeEquality = rule.compare(node1, node2);

            if (nodeEquality != null) {
                // LOG.warning("used rule " + rule + " for equality check");
                return nodeEquality;
            }
        }

        // LOG.warning("no rule could be applied --> handling nodes as unequal");

        return NodeEquality.UNEQUAL;
    }

}
