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

package com.hypixel.hytale.server.core.command.system;

import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.server.core.command.system.exceptions.SenderTypeException;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.command.system.arguments.system.AbstractOptionalArg;
import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.command.system.arguments.system.DefaultArg;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import com.hypixel.hytale.server.core.command.system.arguments.system.Argument;
import java.util.Map;
import javax.annotation.Nonnull;

public final class CommandContext
{
    @Nonnull
    private final AbstractCommand calledCommand;
    @Nonnull
    private final String inputString;
    @Nonnull
    private final CommandSender sender;
    @Nonnull
    private final Map<Argument<?, ?>, Object> argValues;
    @Nonnull
    private final Map<Argument<?, ?>, String[]> argInput;
    
    public CommandContext(@Nonnull final AbstractCommand calledCommand, @Nonnull final CommandSender sender, @Nonnull final String inputString) {
        this.calledCommand = calledCommand;
        this.inputString = inputString;
        this.sender = sender;
        this.argValues = new Object2ObjectOpenHashMap<Argument<?, ?>, Object>();
        this.argInput = new Object2ObjectOpenHashMap<Argument<?, ?>, String[]>();
    }
    
     <DataType> void appendArgumentData(@Nonnull final Argument<?, DataType> argument, @Nonnull final String[] data, final boolean asListArgument, @Nonnull final ParseResult parseResult) {
        if (data.length == 0 && argument instanceof DefaultArg) {
            final DefaultArg<?> defaultArg = (DefaultArg)argument;
            this.argValues.put(argument, defaultArg.getDefaultValue());
            return;
        }
        final int numParameters = argument.getArgumentType().getNumberOfParameters();
        if ((asListArgument && data.length % numParameters != 0) || (!asListArgument && data.length != numParameters)) {
            parseResult.fail(Message.translation("server.commands.parsing.error.wrongNumberOfParametersForArgument").param("argument", argument.getName()).param("expected", argument.getArgumentType().getNumberOfParameters()).param("actual", data.length).param("input", String.join(" ", (CharSequence[])data)));
            return;
        }
        final DataType convertedValue = argument.getArgumentType().parse(data, parseResult);
        if (parseResult.failed()) {
            return;
        }
        argument.validate(convertedValue, parseResult);
        if (parseResult.failed()) {
            return;
        }
        this.argValues.put(argument, convertedValue);
        this.argInput.put(argument, data);
    }
    
    public <DataType> DataType get(@Nonnull final Argument<?, DataType> argument) {
        if (!this.argValues.containsKey(argument) && argument instanceof AbstractOptionalArg.DefaultValueArgument) {
            final AbstractOptionalArg.DefaultValueArgument<?> defaultValueArgument = (AbstractOptionalArg.DefaultValueArgument)argument;
            final Object defaultValue = defaultValueArgument.getDefaultValue();
            this.argValues.put(argument, defaultValue);
            return (DataType)defaultValue;
        }
        return (DataType)this.argValues.get(argument);
    }
    
    public String[] getInput(@Nonnull final Argument<?, ?> argument) {
        return this.argInput.get(argument);
    }
    
    public boolean provided(@Nonnull final Argument<?, ?> argument) {
        return this.argValues.containsKey(argument);
    }
    
    @Nonnull
    public String getInputString() {
        return this.inputString;
    }
    
    public void sendMessage(@Nonnull final Message message) {
        this.sender.sendMessage(message);
    }
    
    public boolean isPlayer() {
        return this.sender instanceof Player;
    }
    
    @Nonnull
    public <T extends CommandSender> T senderAs(@Nonnull final Class<T> senderType) {
        try {
            return senderType.cast(this.sender);
        }
        catch (final ClassCastException e) {
            throw new SenderTypeException(senderType);
        }
    }
    
    @Nullable
    public Ref<EntityStore> senderAsPlayerRef() {
        return this.senderAs(Player.class).getReference();
    }
    
    @Nonnull
    public CommandSender sender() {
        return this.sender;
    }
    
    @Nonnull
    public AbstractCommand getCalledCommand() {
        return this.calledCommand;
    }
}
