package de.renew.expression;

import java.io.Serial;

import de.renew.unify.ICalculationChecker;
import de.renew.unify.IStateRecorder;
import de.renew.unify.Impossible;
import de.renew.util.Value;


/**
 * A {@code ConstantExpression} is an {@code Expression} that always evaluates to the constant value given in the
 * constructor.
 */
public class ConstantExpression extends ExpressionWithTypeField {
    /**
     * A special {@code ConstantExpression} that represents the {@code Double} value {@code 0}.
     */
    public static final Expression DOUBLE_ZERO_EXPRESSION =
        new ConstantExpression(Double.TYPE, new Value(Double.valueOf(0)));
    @Serial
    private static final long serialVersionUID = 6457217584489705338L;
    /**
     * The constant value that the {@code ConstantExpression} evaluates to.
     */
    private final Object _constant;

    /**
     * Constructs a new {@code ConstantExpression} based on a {@code Class} and the constant {@code Object}.
     * @param targetType the type of the {@code ConstantExpression}'s value
     * @param constant the constant value that the {@code ConstantExpression} evaluates to
     */
    public ConstantExpression(Class<?> targetType, Object constant) {
        super(targetType);
        _constant = constant;
    }

    /**
     * Gets the constant value that the {@code ConstantExpression} evaluates to.
     * @return the constant value that the {@code ConstantExpression} evaluates to
     */
    public Object getConstant() {
        return _constant;
    }

    @Override
    public boolean isInvertible() {
        // Because there is only one value that this expression
        // can take, there is really no use in starting a search
        // process.
        return false;
    }

    @Override
    public Object startEvaluation(
        VariableMapper mapper, IStateRecorder recorder, ICalculationChecker checker)
        throws Impossible
    {
        return _constant;
    }

    @Override
    public Object registerCalculation(
        VariableMapper mapper, IStateRecorder recorder, ICalculationChecker checker)
        throws Impossible
    {
        return _constant;
    }

    @Override
    public String toString() {
        return "ConstantExpr(" + de.renew.util.Types.typeToString(getType()) + ": " + _constant
            + ")";
    }
}