package ws.prova.reference;

import org.mandarax.kernel.*;
import org.mandarax.util.logging.LogCategories;
import org.mandarax.reference.SemanticEvaluationPolicy;

import java.util.*;

/**
 * Derivation nodes represent application of a single rule.
 *
 * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
 * @author <A HREF="mailto:a.kozlenkov@city.ac.uk">Alex Kozlenkov</A>
 * @version 3.3.1 <9 August 2004>
 * @since 1.0
 *        Prova re-integration modifications
 */
public class ProvaDerivationNodeImpl implements LogCategories {

//    private List subNodes = new Vector();
    private boolean failed = false;
    private Unification unification = null;

    public void setCurrentGoal(Clause currentGoal) {
        this.currentGoal = currentGoal;
    }

    private Clause currentGoal = null;
    private Clause query = null;
    private ProvaDerivationNodeImpl parent = null;
    private SemanticEvaluationPolicy semanticEvaluationPolicy = null;
//    private static LogicFactory lfactory = DefaultLogicFactory.getDefaultFactory();
    Map varRenamings = new HashMap();
    private int id = 0;
    private boolean isLastNode = false;
    private boolean isResultNode = false;
    private boolean isCut = false;
    // 2.2
    // Further corrections 28/04/03
    private int cutPredicate = -1;

//    private BitSet supportedSolutions = null;

    /**
     * Cache the string representation for optimized debugging.
     */
    private transient String cachedToString = null;

    /**
     * Constructor.
     */
    public ProvaDerivationNodeImpl() {
        super();
    }

    /**
     * Get the applied clause.
     *
     * @return the applied clause
     */
    public Clause getCurrentGoal() {
        return currentGoal;
    }

    /**
     * Get the parent derivation node.
     *
     * @return the parent node
     */
    public ProvaDerivationNodeImpl getParent() {
        return parent;
    }

    /**
     * Get the query.
     *
     * @return the query
     */
    public Clause getQuery() {
        return query;
    }

    /**
     * Get the state of this node.
     *
     * @return the state, the value is one of the constants defined in org.mandarax.kernel.DerivationNodeImpl
     */
    public int getState() {
        return isFailed()
                ? DerivationNode.FAILED
                : DerivationNode.SUCCESS;
    }

    /**
     * Get the unification.
     *
     * @return the unification applied
     */
    public Unification getUnification() {
        return unification;
    }

    /**
     * Indicates whether this derivation step has failed.
     *
     * @return true if this proof step has failed, false otherwise
     */
    public boolean isFailed() {
        return failed;
    }

    /**
     * Set the failed flag.
     *
     * @param f true if this node has failed, false otherwise
     */
    public void setFailed(boolean f) {
        cachedToString = null;
        failed = f;
    }

    /**
     * Set the query.
     *
     * @param f a query
     */
    public void setQuery(Clause f) {
        query = f;
    }

    /**
     * Set the unification.
     *
     * @param u a unification
     */
    public void setUnification(Unification u) {
        unification = u;
    }

    /**
     * Convert the derivation node to a string.
     *
     * @return the string representation of this object
     */
    public String toString() {
        if (cachedToString == null) {
            StringBuffer buf = new StringBuffer();
            buf.append("NODE ");
            buf.append(id);
            buf.append(" : CLAUSE: \"");
            if (getCurrentGoal() == null) {
                buf.append("<NONE>");
            } else
                buf.append(getCurrentGoal().toString());
            buf.append("\" FAILED: ");
            buf.append(isFailed());
            buf.append(" IS_LAST_NODE: ");
            buf.append(this.isLastNode);
            cachedToString = buf.toString();
        }
        return cachedToString;
    }

    /**
     * Returns the semantic evaluation policy.
     *
     * @return the policy
     */
    SemanticEvaluationPolicy getSemanticEvaluationPolicy() {
        return semanticEvaluationPolicy == null ? this.parent.getSemanticEvaluationPolicy() : semanticEvaluationPolicy;
    }

    /**
     * Sets the semantic evaluation policy.
     * [Prova] Changed to public to allow out of package inference engines.
     *
     * @param policy The semantic evaluation policy to set
     */
    public void setSemanticEvaluationPolicy(SemanticEvaluationPolicy policy) {
        this.semanticEvaluationPolicy = policy;
    }

    public boolean isCut() {
        return isCut;
    }

    public void setCut(boolean cut) {
        isCut = cut;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getCutPredicate() {
        return cutPredicate;
    }

    public void setCutPredicate(int cutPredicate) {
        this.cutPredicate = cutPredicate;
    }

    public boolean isLastNode() {
        return isLastNode;
    }

    public void setLastNode(boolean lastNode) {
        isLastNode = lastNode;
    }

    public boolean isResultNode() {
        return isResultNode;
    }

    public void setResultNode(boolean resultNode) {
        isResultNode = resultNode;
    }

	/*
	 * Added for ContractLog inference engine
	 */
	
	/**
	 * Set the parent node.
	 *
	 * @param n a node
	 */
	public void setParent(ProvaDerivationNodeImpl n) {
		parent = n;
	}
}
