// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.asset.builder.expression;

import java.util.Map;
import com.hypixel.hytale.codec.schema.config.StringSchema;
import com.hypixel.hytale.codec.schema.config.ObjectSchema;
import com.hypixel.hytale.codec.schema.config.Schema;
import com.hypixel.hytale.server.npc.util.expression.ValueType;
import com.google.gson.JsonObject;
import com.hypixel.hytale.server.npc.asset.builder.BuilderBase;
import com.hypixel.hytale.server.npc.asset.builder.BuilderParameters;
import com.google.gson.JsonElement;
import java.util.Objects;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.util.expression.ExecutionContext;

public abstract class BuilderExpressionDynamic extends BuilderExpression
{
    public static final String KEY_COMPUTE = "Compute";
    private final String expression;
    private final ExecutionContext.Instruction[] instructionSequence;
    
    public BuilderExpressionDynamic(final String expression, final ExecutionContext.Instruction[] instructionSequence) {
        this.expression = expression;
        this.instructionSequence = instructionSequence;
    }
    
    @Override
    public boolean isStatic() {
        return false;
    }
    
    @Override
    public String getExpression() {
        return this.expression;
    }
    
    protected void execute(@Nonnull final ExecutionContext executionContext) {
        Objects.requireNonNull(executionContext, "ExecutionContext not initialised");
        if (executionContext.execute(this.instructionSequence) != this.getType()) {
            throw new IllegalStateException("Expression returned wrong type " + String.valueOf(executionContext.getType()) + " but expected " + String.valueOf(this.getType()) + ": " + this.expression);
        }
    }
    
    @Nonnull
    public static BuilderExpression fromJSON(@Nonnull final JsonElement jsonElement, @Nonnull final BuilderParameters builderParameters) {
        final JsonObject jsonObject = jsonElement.getAsJsonObject();
        final JsonElement computeValue = jsonObject.get("Compute");
        if (computeValue == null) {
            throw new IllegalArgumentException("JSON expression missing 'Compute' member: " + String.valueOf(jsonElement));
        }
        final String expression = BuilderBase.expectStringElement(computeValue, "Compute");
        final ValueType type = builderParameters.compile(expression);
        final ExecutionContext.Operand operand = builderParameters.getConstantOperand();
        if (operand != null) {
            return BuilderExpression.fromOperand(operand);
        }
        final ExecutionContext.Instruction[] instructionSequence = builderParameters.getInstructions().toArray(ExecutionContext.Instruction[]::new);
        return switch (type) {
            case NUMBER -> new BuilderExpressionDynamicNumber(expression, instructionSequence);
            case STRING -> new BuilderExpressionDynamicString(expression, instructionSequence);
            case BOOLEAN -> new BuilderExpressionDynamicBoolean(expression, instructionSequence);
            case NUMBER_ARRAY -> new BuilderExpressionDynamicNumberArray(expression, instructionSequence);
            case STRING_ARRAY -> new BuilderExpressionDynamicStringArray(expression, instructionSequence);
            case BOOLEAN_ARRAY -> new BuilderExpressionDynamicBooleanArray(expression, instructionSequence);
            default -> throw new IllegalStateException("Unable to create dynamic expression from type " + String.valueOf(type));
        };
    }
    
    @Nonnull
    public static Schema toSchema() {
        final ObjectSchema s = new ObjectSchema();
        s.setTitle("ExpressionDynamic");
        s.setProperties((Map<String, Schema>)Map.of("Compute", new StringSchema()));
        s.setRequired("Compute");
        s.setAdditionalProperties(false);
        return s;
    }
    
    @Nonnull
    public static Schema computableSchema(final Schema toWrap) {
        return Schema.anyOf(toWrap, toSchema());
    }
}
