package ec.app.semanticGP.func.numeric;

import java.util.*;

import library.semantics.*;
import ec.*;
import ec.app.semanticGP.func.*;
import ec.gp.*;
import ec.gp.semantic.*;
import ec.gp.semantic.func.*;

public final class Constant extends NullaryNode<Double> implements IConstant<Double> {
	private final static GPNode[] EMPTY_CHILDREN = new GPNode[0];
	public final static Constant ZERO = new Constant(0.0);
	public final static Constant ONE = new Constant(1.0);
	public final static Constant TWO = new Constant(2.0);
	public final static Constant THREE = new Constant(3.0);
	public final static Constant FOUR = new Constant(4.0);

	private final double value;

	public Constant(double value) {
		this.children = EMPTY_CHILDREN;
		this.value = value;
	}

	public Double getConstant() {
		return this.value;
	}

	@Override
	protected ISemantics execute(ISemantics... arguments) {
		//assert !Double.isNaN(value);
		//assert !Double.isInfinite(value);

		// calculate semantics
		ISemanticProblem<Double> problem = (ISemanticProblem<Double>) this.state.evaluator.p_problem;
		List<TestCase<Double>> cases = problem.getFitnessCases();

		double[] semantics = new double[cases.size()];
		Arrays.fill(semantics, this.value);
		return new DoubleSemantics(semantics);
	}

	@Override
	public String toString() {
		return "" + this.value;
	}

	@Override
	public int nodeHashCode() {
		return this.getConstant().hashCode();
	}

	@Override
	public boolean nodeEquals(GPNode node) {
		if (!(node instanceof IConstant))
			return false;

		IConstant<Double> other = (IConstant<Double>) node;

		assert (this.getConstant() == other.getConstant() && this.nodeHashCode() == node.nodeHashCode())
				|| this.getConstant() != other.getConstant();

		return other.getConstant() == this.getConstant();
	}

	/*@Override
	public Object clone() {
		// this object is immutable, we don't need to copy its memory
		return this;
	}

	@Override
	public GPNode lightClone() {
		// this object is immutable, we don't need to copy its memory
		return this;
	}

	@Override
	public int atDepth() {
		// we cannot determine it, since all clones are the same object
		return Integer.MIN_VALUE;
	}*/
}
