package com.r3944realms.leashedplayer.mixin.server;

import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.TeleportWithLeashedPlayers;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.entity.Relative;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.*;
import java.util.stream.Collectors;

import static com.r3944realms.leashedplayer.utils.Logger.logger;
@Mixin(ServerGamePacketListenerImpl.class)
public class MixinServerGamePacketListenerImpl {

    @Shadow
    public ServerPlayer player;
    @Unique
    private List<Entity> Pl$LeashPlayers = new ArrayList<>();
    @Inject(method = {"teleport(Lnet/minecraft/world/entity/PositionMoveRotation;Ljava/util/Set;)V"}, at = {@At("HEAD")})
    private void teleportHead(PositionMoveRotation positionMoveRotation, Set<Relative> pRelativeSet, CallbackInfo ci) {
        try {
            //獲取Holder
            this.Pl$LeashPlayers = ((PlayerLeashable)this.player).getLeashHolder() != null ? Collections.emptyList() : Objects.requireNonNull(this.player.getServer()).getPlayerList().getPlayers().stream().filter(serverPlayer -> (serverPlayer instanceof PlayerLeashable) && ((PlayerLeashable)serverPlayer).getLeashHolder() == this.player && player != serverPlayer).collect(Collectors.toList());
        } catch (Exception e) {
            logger.error("Internal Error:",e);
        }
    }
    @Inject(method = {"teleport(Lnet/minecraft/world/entity/PositionMoveRotation;Ljava/util/Set;)V"}, at = {@At("TAIL")})
    private void teleportTail(PositionMoveRotation moveRotation, Set<Relative> pRelativeSet, CallbackInfo ci) {
        if(GameruleRegistry.getGameruleBoolValue(this.player.level(), TeleportWithLeashedPlayers.ID)) {
            for (Entity Pl$LeashPlayer : this.Pl$LeashPlayers) {
                if(Pl$LeashPlayer instanceof ServerPlayer) {
                    if(Pl$LeashPlayer instanceof PlayerLeashable playerLeashable) {
                        Leashable.dropLeash((Entity & Leashable) playerLeashable, false,false);
                        if(((ServerPlayer) playerLeashable).level() == this.player.level()) {
                            ((ServerPlayer) playerLeashable).connection.teleport(moveRotation, pRelativeSet);
                        } else {
                            Vec3 vec3 = moveRotation.deltaMovement();
                            ((ServerPlayer) playerLeashable).teleportTo(this.player.level(), vec3.x, vec3.y, vec3.z, pRelativeSet, moveRotation.yRot(), moveRotation.yRot(),false);
                            ((ServerPlayer) playerLeashable).stopRiding();
                        }
                        playerLeashable.setLeashedTo(this.player, true);
                    }
                }
            }
        }
    }
}
