package com.tiedup.remake.network.sync;

import com.tiedup.remake.network.base.AbstractClientPacket;
import java.util.*;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 * Packet to sync collar registry data from server to client.
 *
 * Sends the list of collar wearers (slaves) owned by the receiving player.
 * This allows the client to display slave management UI without spatial queries.
 *
 * Direction: Server → Client (S2C)
 */
public class PacketSyncCollarRegistry extends AbstractClientPacket {

    // Player's owned slaves (wearer UUIDs)
    private final Set<UUID> slaveUUIDs;

    // Full sync flag (true = replace all, false = incremental update)
    private final boolean fullSync;

    // For incremental updates: UUIDs to remove
    private final Set<UUID> removedUUIDs;

    /**
     * Create a full sync packet with all slave UUIDs.
     */
    public PacketSyncCollarRegistry(Set<UUID> slaveUUIDs) {
        this.slaveUUIDs = new HashSet<>(slaveUUIDs);
        this.fullSync = true;
        this.removedUUIDs = Collections.emptySet();
    }

    /**
     * Create an incremental update packet.
     *
     * @param addedUUIDs UUIDs to add to the client's cache
     * @param removedUUIDs UUIDs to remove from the client's cache
     */
    public PacketSyncCollarRegistry(
        Set<UUID> addedUUIDs,
        Set<UUID> removedUUIDs
    ) {
        this.slaveUUIDs = new HashSet<>(addedUUIDs);
        this.fullSync = false;
        this.removedUUIDs = new HashSet<>(removedUUIDs);
    }

    // ==================== ENCODE/DECODE ====================

    public void encode(FriendlyByteBuf buf) {
        buf.writeBoolean(fullSync);

        // Write slave UUIDs
        buf.writeVarInt(slaveUUIDs.size());
        for (UUID uuid : slaveUUIDs) {
            buf.writeUUID(uuid);
        }

        // Write removed UUIDs (only for incremental)
        if (!fullSync) {
            buf.writeVarInt(removedUUIDs.size());
            for (UUID uuid : removedUUIDs) {
                buf.writeUUID(uuid);
            }
        }
    }

    public static PacketSyncCollarRegistry decode(FriendlyByteBuf buf) {
        boolean fullSync = buf.readBoolean();

        // Read slave UUIDs (cap at 10000 to prevent memory exhaustion from malformed packets)
        int slaveCount = Math.min(buf.readVarInt(), 10000);
        Set<UUID> slaveUUIDs = new HashSet<>(slaveCount);
        for (int i = 0; i < slaveCount; i++) {
            slaveUUIDs.add(buf.readUUID());
        }

        if (fullSync) {
            return new PacketSyncCollarRegistry(slaveUUIDs);
        } else {
            // Read removed UUIDs (cap at 10000)
            int removedCount = Math.min(buf.readVarInt(), 10000);
            Set<UUID> removedUUIDs = new HashSet<>(removedCount);
            for (int i = 0; i < removedCount; i++) {
                removedUUIDs.add(buf.readUUID());
            }
            return new PacketSyncCollarRegistry(slaveUUIDs, removedUUIDs);
        }
    }

    // ==================== HANDLE ====================

    @Override
    @OnlyIn(Dist.CLIENT)
    protected void handleClientImpl() {
        if (fullSync) {
            com.tiedup.remake.client.state.CollarRegistryClient.setSlaves(
                slaveUUIDs
            );
        } else {
            com.tiedup.remake.client.state.CollarRegistryClient.updateSlaves(
                slaveUUIDs,
                removedUUIDs
            );
        }
    }

    // ==================== GETTERS ====================

    public Set<UUID> getSlaveUUIDs() {
        return Collections.unmodifiableSet(slaveUUIDs);
    }

    public boolean isFullSync() {
        return fullSync;
    }

    public Set<UUID> getRemovedUUIDs() {
        return Collections.unmodifiableSet(removedUUIDs);
    }
}
