package ec.app.semanticGP.func.classification;

import ec.app.semanticGP.func.IConstant;
import ec.gp.GPNode;
import ec.gp.semantic.ByteSemantics;
import ec.gp.semantic.ISemanticProblem;
import ec.gp.semantic.ISemantics;
import ec.gp.semantic.func.NullaryNode;
import library.semantics.TestCase;

import java.util.Arrays;
import java.util.List;

/**
 * Class n.
 */
public class Cn extends NullaryNode<Byte> implements IConstant<Byte> {
	private final static GPNode[] EMPTY_CHILDREN = new GPNode[0];
	public final static byte UNKNOWN_CLASS = Byte.MIN_VALUE;

	private final static Cn[] CACHE = new Cn[256];

	protected final byte n;

	protected Cn(byte n) {
		this.n = n;
		this.children = EMPTY_CHILDREN;
	}

	public static Cn get(byte n) {
		int idx = n - Byte.MIN_VALUE; // handle negative values
		if (CACHE[idx] == null) {
			CACHE[idx] = new Cn(n);
		}
		return CACHE[idx];
	}

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

		Cn other = (Cn) node;
		return super.nodeEquals(node) && this.n == other.n;
	}

	@Override
	public int nodeHashCode() {
		return super.nodeHashCode() ^ this.n;
	}

	@Override
	protected ISemantics execute(ISemantics... arguments) {
		ISemanticProblem<Byte> problem = (ISemanticProblem<Byte>) this.state.evaluator.p_problem;
		List<TestCase<Byte>> cases = problem.getFitnessCases();

		byte[] semantics = new byte[cases.size()];
		Arrays.fill(semantics, this.n);

		return new ByteSemantics(semantics);
	}

	@Override
	public Byte getConstant() {
		return this.n;
	}

	@Override
	public String toString() {
		return ("C" + this.n).intern();
	}

	@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;
	}
}
