package de.steamwar.fightsystem.listener;

import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentListener;
import de.steamwar.linkage.Linked;
import net.minecraft.network.protocol.game.ClientboundForgetLevelChunkPacket;
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.LevelChunk;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

@Linked
public class PlayerJoinListener implements Listener {

    public PlayerJoinListener() {
        new StateDependentListener(true, FightState.All, this);
    }

    @EventHandler()
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        World world = player.getWorld();

        Location loc = player.getLocation();
        int viewDistance = Bukkit.getViewDistance();

        int chunkX = loc.getChunk().getX();
        int chunkZ = loc.getChunk().getZ();

        // Iterate through the chunks around the player and force a resend
        for (int x = -viewDistance; x <= viewDistance; x++) {
            for (int z = -viewDistance; z <= viewDistance; z++) {
                Chunk chunk = world.getChunkAt(chunkX + x, chunkZ + z);
                this.forceRefreshChunkForPlayer(player, chunk);
            }
        }
    }

    public void forceRefreshChunkForPlayer(Player player, Chunk bukkitChunk) {
        ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
        CraftWorld craftWorld = (CraftWorld) bukkitChunk.getWorld();

        int chunkX = bukkitChunk.getX();
        int chunkZ = bukkitChunk.getZ();

        LevelChunk nmsChunk = craftWorld.getHandle().getChunkSource().getChunk(chunkX, chunkZ, false);
        if (nmsChunk == null) {
            // Chunk isn't loaded in memory on the server side;
            return;
        }

        ClientboundForgetLevelChunkPacket unloadPacket = new ClientboundForgetLevelChunkPacket(new ChunkPos(chunkX, chunkZ));
        serverPlayer.connection.send(unloadPacket);

        ClientboundLevelChunkWithLightPacket loadPacket = new ClientboundLevelChunkWithLightPacket(
                nmsChunk,
                craftWorld.getHandle().getLightEngine(),
                null,
                null,
                true
        );
        serverPlayer.connection.send(loadPacket);
    }
}
