package net.minecraft.server.commands;

import net.minecraft.commands.arguments.coordinates.WorldCoordinates;
import java.util.Collections;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.util.Mth;
import net.minecraft.server.level.TicketType;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import javax.annotation.Nullable;
import net.minecraft.commands.arguments.coordinates.Coordinates;
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;

public class TeleportCommand {
    public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
        final LiteralCommandNode<CommandSourceStack> literalCommandNode2 = (LiteralCommandNode<CommandSourceStack>)commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("teleport").requires(cq -> cq.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(cq -> cq.hasPermission(2))).redirect((CommandNode)literalCommandNode2));
    }
    
    private static int teleportToEntity(final CommandSourceStack cq, final Collection<? extends Entity> collection, final Entity akq) {
        for (final Entity akq2 : collection) {
            performTeleport(cq, akq2, (ServerLevel)akq.level, akq.getX(), akq.getY(), akq.getZ(), EnumSet.<ClientboundPlayerPositionPacket.RelativeArgument>noneOf(ClientboundPlayerPositionPacket.RelativeArgument.class), akq.yRot, akq.xRot, null);
        }
        if (collection.size() == 1) {
            cq.sendSuccess(new TranslatableComponent("commands.teleport.success.entity.single", new Object[] { ((Entity)collection.iterator().next()).getDisplayName(), akq.getDisplayName() }), true);
        }
        else {
            cq.sendSuccess(new TranslatableComponent("commands.teleport.success.entity.multiple", new Object[] { collection.size(), akq.getDisplayName() }), true);
        }
        return collection.size();
    }
    
    private static int teleportToPos(final CommandSourceStack cq, final Collection<? extends Entity> collection, final ServerLevel xd, final Coordinates dz4, @Nullable final Coordinates dz5, @Nullable final LookAt a) throws CommandSyntaxException {
        final Vec3 cvl7 = dz4.getPosition(cq);
        final Vec2 cvk8 = (dz5 == null) ? null : dz5.getRotation(cq);
        final Set<ClientboundPlayerPositionPacket.RelativeArgument> set9 = EnumSet.<ClientboundPlayerPositionPacket.RelativeArgument>noneOf(ClientboundPlayerPositionPacket.RelativeArgument.class);
        if (dz4.isXRelative()) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.X);
        }
        if (dz4.isYRelative()) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Y);
        }
        if (dz4.isZRelative()) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Z);
        }
        if (dz5 == null) {
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.X_ROT);
            set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Y_ROT);
        }
        else {
            if (dz5.isXRelative()) {
                set9.add(ClientboundPlayerPositionPacket.RelativeArgument.X_ROT);
            }
            if (dz5.isYRelative()) {
                set9.add(ClientboundPlayerPositionPacket.RelativeArgument.Y_ROT);
            }
        }
        for (final Entity akq11 : collection) {
            if (dz5 == null) {
                performTeleport(cq, akq11, xd, cvl7.x, cvl7.y, cvl7.z, set9, akq11.yRot, akq11.xRot, a);
            }
            else {
                performTeleport(cq, akq11, xd, cvl7.x, cvl7.y, cvl7.z, set9, cvk8.y, cvk8.x, a);
            }
        }
        if (collection.size() == 1) {
            cq.sendSuccess(new TranslatableComponent("commands.teleport.success.location.single", new Object[] { ((Entity)collection.iterator().next()).getDisplayName(), cvl7.x, cvl7.y, cvl7.z }), true);
        }
        else {
            cq.sendSuccess(new TranslatableComponent("commands.teleport.success.location.multiple", new Object[] { collection.size(), cvl7.x, cvl7.y, cvl7.z }), true);
        }
        return collection.size();
    }
    
    private static void performTeleport(final CommandSourceStack cq, Entity akq, final ServerLevel xd, final double double4, final double double5, final double double6, final Set<ClientboundPlayerPositionPacket.RelativeArgument> set, final float float8, final float float9, @Nullable final LookAt a) {
        if (akq instanceof ServerPlayer) {
            final ChunkPos bjh14 = new ChunkPos(new BlockPos(double4, double5, double6));
            xd.getChunkSource().<Integer>addRegionTicket(TicketType.POST_TELEPORT, bjh14, 1, akq.getId());
            akq.stopRiding();
            if (((ServerPlayer)akq).isSleeping()) {
                ((ServerPlayer)akq).stopSleepInBed(true, true);
            }
            if (xd == akq.level) {
                ((ServerPlayer)akq).connection.teleport(double4, double5, double6, float8, float9, set);
            }
            else {
                ((ServerPlayer)akq).teleportTo(xd, double4, double5, double6, float8, float9);
            }
            akq.setYHeadRot(float8);
        }
        else {
            final float float10 = Mth.wrapDegrees(float8);
            float float11 = Mth.wrapDegrees(float9);
            float11 = Mth.clamp(float11, -90.0f, 90.0f);
            if (xd == akq.level) {
                akq.moveTo(double4, double5, double6, float10, float11);
                akq.setYHeadRot(float10);
            }
            else {
                akq.unRide();
                akq.dimension = xd.dimension.getType();
                final Entity akq2 = akq;
                akq = (Entity)akq2.getType().create(xd);
                if (akq == null) {
                    return;
                }
                akq.restoreFrom(akq2);
                akq.moveTo(double4, double5, double6, float10, float11);
                akq.setYHeadRot(float10);
                xd.addFromAnotherDimension(akq);
                akq2.removed = true;
            }
        }
        if (a != null) {
            a.perform(cq, akq);
        }
        if (!(akq instanceof LivingEntity) || !((LivingEntity)akq).isFallFlying()) {
            akq.setDeltaMovement(akq.getDeltaMovement().multiply(1.0, 0.0, 1.0));
            akq.onGround = true;
        }
    }
    
    static class LookAt {
        private final Vec3 position;
        private final Entity entity;
        private final EntityAnchorArgument.Anchor anchor;
        
        public LookAt(final Entity akq, final EntityAnchorArgument.Anchor a) {
            this.entity = akq;
            this.anchor = a;
            this.position = a.apply(akq);
        }
        
        public LookAt(final Vec3 cvl) {
            this.entity = null;
            this.position = cvl;
            this.anchor = null;
        }
        
        public void perform(final CommandSourceStack cq, final Entity akq) {
            if (this.entity != null) {
                if (akq instanceof ServerPlayer) {
                    ((ServerPlayer)akq).lookAt(cq.getAnchor(), this.entity, this.anchor);
                }
                else {
                    akq.lookAt(cq.getAnchor(), this.position);
                }
            }
            else {
                akq.lookAt(cq.getAnchor(), this.position);
            }
        }
    }
}
