package net.minecraft.server.commands;

import com.mojang.brigadier.Message;
import net.minecraft.commands.arguments.coordinates.WorldCoordinates;
import java.util.Collections;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.util.Mth;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import net.minecraft.commands.arguments.coordinates.Coordinates;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.Iterator;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import java.util.Set;
import java.util.EnumSet;
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import java.util.Collection;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.CommandNode;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.commands.arguments.coordinates.RotationArgument;
import net.minecraft.commands.arguments.coordinates.Vec3Argument;
import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.commands.arguments.EntityArgument;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import net.minecraft.commands.Commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;

public class TeleportCommand {
    private static final SimpleCommandExceptionType INVALID_POSITION;
    
    public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
        final LiteralCommandNode<CommandSourceStack> literalCommandNode2 = (LiteralCommandNode<CommandSourceStack>)commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("teleport").requires(cz -> cz.hasPermission(2))).then(((RequiredArgumentBuilder)Commands.argument("targets", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.entities()).then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("location", (com.mojang.brigadier.arguments.ArgumentType<Object>)Vec3Argument.vec3()).executes(commandContext -> teleportToPos((CommandSourceStack)commandContext.getSource(), EntityArgument.getEntities((CommandContext<CommandSourceStack>)commandContext, "targets"), ((CommandSourceStack)commandContext.getSource()).getLevel(), Vec3Argument.getCoordinates((CommandContext<CommandSourceStack>)commandContext, "location"), null, null))).then(Commands.argument("rotation", (com.mojang.brigadier.arguments.ArgumentType<Object>)RotationArgument.rotation()).executes(commandContext -> teleportToPos((CommandSourceStack)commandContext.getSource(), EntityArgument.getEntities((CommandContext<CommandSourceStack>)commandContext, "targets"), ((CommandSourceStack)commandContext.getSource()).getLevel(), Vec3Argument.getCoordinates((CommandContext<CommandSourceStack>)commandContext, "location"), RotationArgument.getRotation((CommandContext<CommandSourceStack>)commandContext, "rotation"), null)))).then(((LiteralArgumentBuilder)Commands.literal("facing").then(Commands.literal("entity").then(((RequiredArgumentBuilder)Commands.argument("facingEntity", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.entity()).executes(commandContext -> teleportToPos((CommandSourceStack)commandContext.getSource(), EntityArgument.getEntities((CommandContext<CommandSourceStack>)commandContext, "targets"), ((CommandSourceStack)commandContext.getSource()).getLevel(), Vec3Argument.getCoordinates((CommandContext<CommandSourceStack>)commandContext, "location"), null, new LookAt(EntityArgument.getEntity((CommandContext<CommandSourceStack>)commandContext, "facingEntity"), EntityAnchorArgument.Anchor.FEET)))).then(Commands.argument("facingAnchor", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityAnchorArgument.anchor()).executes(commandContext -> teleportToPos((CommandSourceStack)commandContext.getSource(), EntityArgument.getEntities((CommandContext<CommandSourceStack>)commandContext, "targets"), ((CommandSourceStack)commandContext.getSource()).getLevel(), Vec3Argument.getCoordinates((CommandContext<CommandSourceStack>)commandContext, "location"), null, new LookAt(EntityArgument.getEntity((CommandContext<CommandSourceStack>)commandContext, "facingEntity"), EntityAnchorArgument.getAnchor((CommandContext<CommandSourceStack>)commandContext, "facingAnchor")))))))).then(Commands.argument("facingLocation", (com.mojang.brigadier.arguments.ArgumentType<Object>)Vec3Argument.vec3()).executes(commandContext -> teleportToPos((CommandSourceStack)commandContext.getSource(), EntityArgument.getEntities((CommandContext<CommandSourceStack>)commandContext, "targets"), ((CommandSourceStack)commandContext.getSource()).getLevel(), Vec3Argument.getCoordinates((CommandContext<CommandSourceStack>)commandContext, "location"), null, new LookAt(Vec3Argument.getVec3((CommandContext<CommandSourceStack>)commandContext, "facingLocation")))))))).then(Commands.argument("destination", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.entity()).executes(commandContext -> teleportToEntity((CommandSourceStack)commandContext.getSource(), EntityArgument.getEntities((CommandContext<CommandSourceStack>)commandContext, "targets"), EntityArgument.getEntity((CommandContext<CommandSourceStack>)commandContext, "destination")))))).then(Commands.argument("location", (com.mojang.brigadier.arguments.ArgumentType<Object>)Vec3Argument.vec3()).executes(commandContext -> teleportToPos((CommandSourceStack)commandContext.getSource(), Collections.<Entity>singleton(((CommandSourceStack)commandContext.getSource()).getEntityOrException()), ((CommandSourceStack)commandContext.getSource()).getLevel(), Vec3Argument.getCoordinates((CommandContext<CommandSourceStack>)commandContext, "location"), WorldCoordinates.current(), null)))).then(Commands.argument("destination", (com.mojang.brigadier.arguments.ArgumentType<Object>)EntityArgument.entity()).executes(commandContext -> teleportToEntity((CommandSourceStack)commandContext.getSource(), Collections.<Entity>singleton(((CommandSourceStack)commandContext.getSource()).getEntityOrException()), EntityArgument.getEntity((CommandContext<CommandSourceStack>)commandContext, "destination")))));
        commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("tp").requires(cz -> cz.hasPermission(2))).redirect((CommandNode)literalCommandNode2));
    }
    
    private static int teleportToEntity(final CommandSourceStack cz, final Collection<? extends Entity> collection, final Entity aom) throws CommandSyntaxException {
        for (final Entity aom2 : collection) {
            performTeleport(cz, aom2, (ServerLevel)aom.level, aom.getX(), aom.getY(), aom.getZ(), EnumSet.<ClientboundPlayerPositionPacket.RelativeArgument>noneOf(ClientboundPlayerPositionPacket.RelativeArgument.class), aom.yRot, aom.xRot, null);
        }
        if (collection.size() == 1) {
            cz.sendSuccess(new TranslatableComponent("commands.teleport.success.entity.single", new Object[] { ((Entity)collection.iterator().next()).getDisplayName(), aom.getDisplayName() }), true);
        }
        else {
            cz.sendSuccess(new TranslatableComponent("commands.teleport.success.entity.multiple", new Object[] { collection.size(), aom.getDisplayName() }), true);
        }
        return collection.size();
    }
    
    private static int teleportToPos(final CommandSourceStack cz, final Collection<? extends Entity> collection, final ServerLevel zd, final Coordinates ej4, @Nullable final Coordinates ej5, @Nullable final LookAt a) throws CommandSyntaxException {
        final Vec3 dem7 = ej4.getPosition(cz);
        final Vec2 del8 = (ej5 == null) ? null : ej5.getRotation(cz);
        final Set<ClientboundPlayerPositionPacket.RelativeArgument> set9 = EnumSet.<ClientboundPlayerPositionPacket.RelativeArgument>noneOf(ClientboundPlayerPositionPacket.RelativeArgument.class);
        if (ej4.isXRelative()) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.X);
        }
        if (ej4.isYRelative()) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Y);
        }
        if (ej4.isZRelative()) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Z);
        }
        if (ej5 == null) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.X_ROT);
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Y_ROT);
        }
        else {
            if (ej5.isXRelative()) {
                set9.add(ClientboundPlayerPositionPacket.RelativeArgument.X_ROT);
            }
            if (ej5.isYRelative()) {
                set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Y_ROT);
            }
        }
        for (final Entity aom11 : collection) {
            if (ej5 == null) {
                performTeleport(cz, aom11, zd, dem7.x, dem7.y, dem7.z, set9, aom11.yRot, aom11.xRot, a);
            }
            else {
                performTeleport(cz, aom11, zd, dem7.x, dem7.y, dem7.z, set9, del8.y, del8.x, a);
            }
        }
        if (collection.size() == 1) {
            cz.sendSuccess(new TranslatableComponent("commands.teleport.success.location.single", new Object[] { ((Entity)collection.iterator().next()).getDisplayName(), dem7.x, dem7.y, dem7.z }), true);
        }
        else {
            cz.sendSuccess(new TranslatableComponent("commands.teleport.success.location.multiple", new Object[] { collection.size(), dem7.x, dem7.y, dem7.z }), true);
        }
        return collection.size();
    }
    
    private static void performTeleport(final CommandSourceStack cz, Entity aom, final ServerLevel zd, final double double4, final double double5, final double double6, final Set<ClientboundPlayerPositionPacket.RelativeArgument> set, final float float8, final float float9, @Nullable final LookAt a) throws CommandSyntaxException {
        final BlockPos fu14 = new BlockPos(double4, double5, double6);
        if (!Level.isInSpawnableBounds(fu14)) {
            throw TeleportCommand.INVALID_POSITION.create();
        }
        if (aom instanceof ServerPlayer) {
            final ChunkPos bph15 = new ChunkPos(new BlockPos(double4, double5, double6));
            zd.getChunkSource().<Integer>addRegionTicket(TicketType.POST_TELEPORT, bph15, 1, aom.getId());
            aom.stopRiding();
            if (((ServerPlayer)aom).isSleeping()) {
                ((ServerPlayer)aom).stopSleepInBed(true, true);
            }
            if (zd == aom.level) {
                ((ServerPlayer)aom).connection.teleport(double4, double5, double6, float8, float9, set);
            }
            else {
                ((ServerPlayer)aom).teleportTo(zd, double4, double5, double6, float8, float9);
            }
            aom.setYHeadRot(float8);
        }
        else {
            final float float10 = Mth.wrapDegrees(float8);
            float float11 = Mth.wrapDegrees(float9);
            float11 = Mth.clamp(float11, -90.0f, 90.0f);
            if (zd == aom.level) {
                aom.moveTo(double4, double5, double6, float10, float11);
                aom.setYHeadRot(float10);
            }
            else {
                aom.unRide();
                final Entity aom2 = aom;
                aom = (Entity)aom2.getType().create(zd);
                if (aom == null) {
                    return;
                }
                aom.restoreFrom(aom2);
                aom.moveTo(double4, double5, double6, float10, float11);
                aom.setYHeadRot(float10);
                zd.addFromAnotherDimension(aom);
                aom2.removed = true;
            }
        }
        if (a != null) {
            a.perform(cz, aom);
        }
        if (!(aom instanceof LivingEntity) || !((LivingEntity)aom).isFallFlying()) {
            aom.setDeltaMovement(aom.getDeltaMovement().multiply(1.0, 0.0, 1.0));
            aom.setOnGround(true);
        }
        if (aom instanceof PathfinderMob) {
            ((PathfinderMob)aom).getNavigation().stop();
        }
    }
    
    static {
        INVALID_POSITION = new SimpleCommandExceptionType((Message)new TranslatableComponent("commands.teleport.invalidPosition"));
    }
    
    static class LookAt {
        private final Vec3 position;
        private final Entity entity;
        private final EntityAnchorArgument.Anchor anchor;
        
        public LookAt(final Entity aom, final EntityAnchorArgument.Anchor a) {
            this.entity = aom;
            this.anchor = a;
            this.position = a.apply(aom);
        }
        
        public LookAt(final Vec3 dem) {
            this.entity = null;
            this.position = dem;
            this.anchor = null;
        }
        
        public void perform(final CommandSourceStack cz, final Entity aom) {
            if (this.entity != null) {
                if (aom instanceof ServerPlayer) {
                    ((ServerPlayer)aom).lookAt(cz.getAnchor(), this.entity, this.anchor);
                }
                else {
                    aom.lookAt(cz.getAnchor(), this.position);
                }
            }
            else {
                aom.lookAt(cz.getAnchor(), this.position);
            }
        }
    }
}
