package net.minecraft.commands;

import com.mojang.brigadier.Message;
import net.minecraft.world.level.Level;
import net.minecraft.resources.ResourceKey;
import java.util.Set;
import com.mojang.brigadier.suggestion.Suggestions;
import java.util.concurrent.CompletableFuture;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import java.util.stream.Stream;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import com.google.common.collect.Lists;
import java.util.Collection;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.network.chat.TextComponent;
import java.util.Iterator;
import net.minecraft.world.level.GameRules;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.Util;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.function.BinaryOperator;
import net.minecraft.world.phys.Vec2;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import com.mojang.brigadier.ResultConsumer;
import javax.annotation.Nullable;
import net.minecraft.world.entity.Entity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.phys.Vec3;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;

public class CommandSourceStack implements SharedSuggestionProvider {
    public static final SimpleCommandExceptionType ERROR_NOT_PLAYER;
    public static final SimpleCommandExceptionType ERROR_NOT_ENTITY;
    private final CommandSource source;
    private final Vec3 worldPosition;
    private final ServerLevel level;
    private final int permissionLevel;
    private final String textName;
    private final Component displayName;
    private final MinecraftServer server;
    private final boolean silent;
    @Nullable
    private final Entity entity;
    private final ResultConsumer<CommandSourceStack> consumer;
    private final EntityAnchorArgument.Anchor anchor;
    private final Vec2 rotation;
    
    public CommandSourceStack(final CommandSource cy, final Vec3 dem, final Vec2 del, final ServerLevel zd, final int integer, final String string, final Component mr, final MinecraftServer minecraftServer, @Nullable final Entity aom) {
        this(cy, dem, del, zd, integer, string, mr, minecraftServer, aom, false, (ResultConsumer<CommandSourceStack>)((commandContext, boolean2, integer) -> {}), EntityAnchorArgument.Anchor.FEET);
    }
    
    protected CommandSourceStack(final CommandSource cy, final Vec3 dem, final Vec2 del, final ServerLevel zd, final int integer, final String string, final Component mr, final MinecraftServer minecraftServer, @Nullable final Entity aom, final boolean boolean10, final ResultConsumer<CommandSourceStack> resultConsumer, final EntityAnchorArgument.Anchor a) {
        this.source = cy;
        this.worldPosition = dem;
        this.level = zd;
        this.silent = boolean10;
        this.entity = aom;
        this.permissionLevel = integer;
        this.textName = string;
        this.displayName = mr;
        this.server = minecraftServer;
        this.consumer = resultConsumer;
        this.anchor = a;
        this.rotation = del;
    }
    
    public CommandSourceStack withEntity(final Entity aom) {
        if (this.entity == aom) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, aom.getName().getString(), aom.getDisplayName(), this.server, aom, this.silent, this.consumer, this.anchor);
    }
    
    public CommandSourceStack withPosition(final Vec3 dem) {
        if (this.worldPosition.equals(dem)) {
            return this;
        }
        return new CommandSourceStack(this.source, dem, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.consumer, this.anchor);
    }
    
    public CommandSourceStack withRotation(final Vec2 del) {
        if (this.rotation.equals(del)) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, del, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.consumer, this.anchor);
    }
    
    public CommandSourceStack withCallback(final ResultConsumer<CommandSourceStack> resultConsumer) {
        if (this.consumer.equals(resultConsumer)) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, resultConsumer, this.anchor);
    }
    
    public CommandSourceStack withCallback(final ResultConsumer<CommandSourceStack> resultConsumer, final BinaryOperator<ResultConsumer<CommandSourceStack>> binaryOperator) {
        final ResultConsumer<CommandSourceStack> resultConsumer2 = (ResultConsumer<CommandSourceStack>)binaryOperator.apply(this.consumer, resultConsumer);
        return this.withCallback(resultConsumer2);
    }
    
    public CommandSourceStack withSuppressedOutput() {
        if (this.silent) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, true, this.consumer, this.anchor);
    }
    
    public CommandSourceStack withPermission(final int integer) {
        if (integer == this.permissionLevel) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, integer, this.textName, this.displayName, this.server, this.entity, this.silent, this.consumer, this.anchor);
    }
    
    public CommandSourceStack withMaximumPermission(final int integer) {
        if (integer <= this.permissionLevel) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, integer, this.textName, this.displayName, this.server, this.entity, this.silent, this.consumer, this.anchor);
    }
    
    public CommandSourceStack withAnchor(final EntityAnchorArgument.Anchor a) {
        if (a == this.anchor) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, this.level, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.consumer, a);
    }
    
    public CommandSourceStack withLevel(final ServerLevel zd) {
        if (zd == this.level) {
            return this;
        }
        return new CommandSourceStack(this.source, this.worldPosition, this.rotation, zd, this.permissionLevel, this.textName, this.displayName, this.server, this.entity, this.silent, this.consumer, this.anchor);
    }
    
    public CommandSourceStack facing(final Entity aom, final EntityAnchorArgument.Anchor a) throws CommandSyntaxException {
        return this.facing(a.apply(aom));
    }
    
    public CommandSourceStack facing(final Vec3 dem) throws CommandSyntaxException {
        final Vec3 dem2 = this.anchor.apply(this);
        final double double4 = dem.x - dem2.x;
        final double double5 = dem.y - dem2.y;
        final double double6 = dem.z - dem2.z;
        final double double7 = Mth.sqrt(double4 * double4 + double6 * double6);
        final float float12 = Mth.wrapDegrees((float)(-(Mth.atan2(double5, double7) * 57.2957763671875)));
        final float float13 = Mth.wrapDegrees((float)(Mth.atan2(double6, double4) * 57.2957763671875) - 90.0f);
        return this.withRotation(new Vec2(float12, float13));
    }
    
    public Component getDisplayName() {
        return this.displayName;
    }
    
    public String getTextName() {
        return this.textName;
    }
    
    @Override
    public boolean hasPermission(final int integer) {
        return this.permissionLevel >= integer;
    }
    
    public Vec3 getPosition() {
        return this.worldPosition;
    }
    
    public ServerLevel getLevel() {
        return this.level;
    }
    
    @Nullable
    public Entity getEntity() {
        return this.entity;
    }
    
    public Entity getEntityOrException() throws CommandSyntaxException {
        if (this.entity == null) {
            throw CommandSourceStack.ERROR_NOT_ENTITY.create();
        }
        return this.entity;
    }
    
    public ServerPlayer getPlayerOrException() throws CommandSyntaxException {
        if (!(this.entity instanceof ServerPlayer)) {
            throw CommandSourceStack.ERROR_NOT_PLAYER.create();
        }
        return (ServerPlayer)this.entity;
    }
    
    public Vec2 getRotation() {
        return this.rotation;
    }
    
    public MinecraftServer getServer() {
        return this.server;
    }
    
    public EntityAnchorArgument.Anchor getAnchor() {
        return this.anchor;
    }
    
    public void sendSuccess(final Component mr, final boolean boolean2) {
        if (this.source.acceptsSuccess() && !this.silent) {
            this.source.sendMessage(mr, Util.NIL_UUID);
        }
        if (boolean2 && this.source.shouldInformAdmins() && !this.silent) {
            this.broadcastToAdmins(mr);
        }
    }
    
    private void broadcastToAdmins(final Component mr) {
        final Component mr2 = new TranslatableComponent("chat.type.admin", new Object[] { this.getDisplayName(), mr }).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC);
        if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) {
            for (final ServerPlayer ze5 : this.server.getPlayerList().getPlayers()) {
                if (ze5 != this.source && this.server.getPlayerList().isOp(ze5.getGameProfile())) {
                    ze5.sendMessage(mr2, Util.NIL_UUID);
                }
            }
        }
        if (this.source != this.server && this.server.getGameRules().getBoolean(GameRules.RULE_LOGADMINCOMMANDS)) {
            this.server.sendMessage(mr2, Util.NIL_UUID);
        }
    }
    
    public void sendFailure(final Component mr) {
        if (this.source.acceptsFailure() && !this.silent) {
            this.source.sendMessage(new TextComponent("").append(mr).withStyle(ChatFormatting.RED), Util.NIL_UUID);
        }
    }
    
    public void onCommandComplete(final CommandContext<CommandSourceStack> commandContext, final boolean boolean2, final int integer) {
        if (this.consumer != null) {
            this.consumer.onCommandComplete((CommandContext)commandContext, boolean2, integer);
        }
    }
    
    @Override
    public Collection<String> getOnlinePlayerNames() {
        return Lists.<String>newArrayList(this.server.getPlayerNames());
    }
    
    @Override
    public Collection<String> getAllTeams() {
        return this.server.getScoreboard().getTeamNames();
    }
    
    @Override
    public Collection<ResourceLocation> getAvailableSoundEvents() {
        return Registry.SOUND_EVENT.keySet();
    }
    
    @Override
    public Stream<ResourceLocation> getRecipeNames() {
        return this.server.getRecipeManager().getRecipeIds();
    }
    
    @Override
    public CompletableFuture<Suggestions> customSuggestion(final CommandContext<SharedSuggestionProvider> commandContext, final SuggestionsBuilder suggestionsBuilder) {
        return null;
    }
    
    @Override
    public Set<ResourceKey<Level>> levels() {
        return this.server.levelKeys();
    }
    
    static {
        ERROR_NOT_PLAYER = new SimpleCommandExceptionType((Message)new TranslatableComponent("permissions.requires.player"));
        ERROR_NOT_ENTITY = new SimpleCommandExceptionType((Message)new TranslatableComponent("permissions.requires.entity"));
    }
}
