package ac.essex.gp.nodes;

import ac.essex.gp.tree.Node;
import ac.essex.gp.util.DataStack;
import ac.essex.gp.params.ADFNodeParams;
import ac.essex.gp.nodes.ercs.BasicERC;

/**
 * ADF Nodes behave like an ERC although they execute a tree of their own. An ADF originalNode
 * has a unique ID that is used to identify itself so the performance of each ADF originalNode can
 * be measured.
 *
 * @author Olly Oechsle, University of Essex, Date: 07-Mar-2007
 * @version 1.0
 */
public class ADFNode extends Node {

    protected Node subtree;
    protected int returnType;

    /**
     * Reference to the ADF Node Params object that created this ADF Node
     */
    protected long id;

    public ADFNode(long id, Node subtree, int returnType) {
        // no children
        super(0);
        this.id = id;
        this.subtree = subtree;
        this.returnType = returnType;
    }


    /**
     * Allows the node to refer to the nodeParams object that created it
    **/
    public long getID() {
        return id;
    }

    public double execute(DataStack data) {
        return subtree.execute(data);
    }

    public int getReturnType() {
        return returnType;
    }

    public String toJava() {
        return "method" + id + "()";
    }                   

    public int getChildType(int index) {
        return 0;
    }

    public Node getTree() {
        return subtree;
    }

    /**
     * Provides information about this node which is used by the tree builder and allows the me to be copied (via
     * the NodeParams getInstance() method.
     */
    public ADFNodeParams createNodeParamsObject() {
        return new ADFNodeParams(this, getReturnType());
    }

    /**
     * Jitters the ERCs in the ADF
     */
    public void jitter() {
        jitter(subtree);
    }

    /**
     * What the hell does this do?
     */
    private void jitter(Node root) {
        System.out.println("ROOT JITTER");
        if (root instanceof BasicERC) {
            ((BasicERC) root).mutate();
        }
        for (int i = 0; i < root.child.length; i++) {
            Node child = root.child[i];
            jitter(child);
        }
    }
   
}
