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

package com.hypixel.hytale.server.npc.util.expression;

import java.util.Arrays;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.Collection;
import java.util.List;
import com.hypixel.hytale.server.npc.util.expression.compile.CompileContext;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.npc.util.expression.compile.Token;
import com.hypixel.hytale.server.npc.util.expression.compile.Lexer;

public class Expression
{
    private static final Lexer<Token> lexer;
    @Nonnull
    private final ExecutionContext executionContext;
    @Nonnull
    private final CompileContext compileContext;
    
    public Expression() {
        this.compileContext = new CompileContext();
        this.executionContext = this.compileContext.getExecutionContext();
    }
    
    public ValueType compile(@Nonnull final String expression, final Scope scope, @Nonnull final List<ExecutionContext.Instruction> instructions, final boolean fullResolve) {
        this.compileContext.compile(expression, scope, fullResolve);
        instructions.clear();
        instructions.addAll(this.compileContext.getInstructions());
        return this.compileContext.getResultType();
    }
    
    public ValueType compile(@Nonnull final String expression, final Scope compileScope, @Nonnull final List<ExecutionContext.Instruction> instructions) {
        return this.compile(expression, compileScope, instructions, false);
    }
    
    @Nonnull
    public ExecutionContext execute(@Nonnull final List<ExecutionContext.Instruction> instructions, final Scope scope) {
        this.executionContext.execute(instructions, scope);
        return this.executionContext;
    }
    
    @Nonnull
    public ExecutionContext execute(@Nonnull final ExecutionContext.Instruction[] instructions, final Scope scope) {
        this.executionContext.execute(instructions, scope);
        return this.executionContext;
    }
    
    @Nonnull
    public ExecutionContext evaluate(@Nonnull final String expression, final Scope scope) {
        final List<ExecutionContext.Instruction> instructions = new ObjectArrayList<ExecutionContext.Instruction>();
        this.compile(expression, scope, instructions, true);
        return this.execute(instructions, scope);
    }
    
    public static ValueType compileStatic(@Nonnull final String expression, final Scope scope, @Nonnull final List<ExecutionContext.Instruction> instructions) {
        final CompileContext compileContext = new CompileContext();
        compileContext.compile(expression, scope, false);
        instructions.clear();
        instructions.addAll(compileContext.getInstructions());
        return compileContext.getResultType();
    }
    
    @Nonnull
    public static Lexer<Token> getLexerInstance() {
        return Expression.lexer;
    }
    
    static {
        lexer = new Lexer<Token>(Token.END, Token.IDENTIFIER, Token.STRING, Token.NUMBER, Arrays.stream(Token.values()).filter(token -> token.get() != null));
    }
}
