package com.tiedup.remake.network.sync;

import com.tiedup.remake.network.base.AbstractPlayerSyncPacket;
import com.tiedup.remake.state.PlayerBindState;
import java.util.UUID;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 * Packet to synchronize player bondage state (tied, gagged, etc.).
 * Sends boolean flags for bind state (lighter than full equipment sync).
 *
 * Direction: Server → Client (S2C)
 */
public class PacketSyncBindState extends AbstractPlayerSyncPacket {

    private final byte stateFlags; // Packed boolean flags

    // Bit flags for state
    private static final byte FLAG_TIED_UP = 1 << 0; // 0x01
    private static final byte FLAG_GAGGED = 1 << 1; // 0x02
    private static final byte FLAG_BLINDFOLDED = 1 << 2; // 0x04
    private static final byte FLAG_HAS_EARPLUGS = 1 << 3; // 0x08
    private static final byte FLAG_HAS_COLLAR = 1 << 4; // 0x10
    private static final byte FLAG_HAS_CLOTHES = 1 << 5; // 0x20
    private static final byte FLAG_ONLINE = 1 << 6; // 0x40

    /**
     * Create a packet to sync a player's bondage state.
     *
     * @param playerUUID The player's UUID
     * @param stateFlags Packed boolean flags
     */
    private PacketSyncBindState(UUID playerUUID, byte stateFlags) {
        super(playerUUID);
        this.stateFlags = stateFlags;
    }

    /**
     * Create a packet from a player's current state.
     *
     * @param player The player
     * @return The packet, or null if player has no state
     */
    public static PacketSyncBindState fromPlayer(Player player) {
        PlayerBindState state = PlayerBindState.getInstance(player);
        if (state == null) {
            return null;
        }

        byte flags = 0;
        if (state.isTiedUp()) flags |= FLAG_TIED_UP;
        if (state.isGagged()) flags |= FLAG_GAGGED;
        if (state.isBlindfolded()) flags |= FLAG_BLINDFOLDED;
        if (state.hasEarplugs()) flags |= FLAG_HAS_EARPLUGS;
        if (state.hasCollar()) flags |= FLAG_HAS_COLLAR;
        if (state.hasClothes()) flags |= FLAG_HAS_CLOTHES;
        if (state.isOnline()) flags |= FLAG_ONLINE;

        return new PacketSyncBindState(player.getUUID(), flags);
    }

    /**
     * Encode the packet to a byte buffer.
     */
    public void encode(FriendlyByteBuf buf) {
        encodeUUID(buf);
        buf.writeByte(stateFlags);
    }

    /**
     * Decode the packet from a byte buffer.
     */
    public static PacketSyncBindState decode(FriendlyByteBuf buf) {
        UUID playerUUID = decodeUUID(buf);
        byte stateFlags = buf.readByte();
        return new PacketSyncBindState(playerUUID, stateFlags);
    }

    /**
     * Apply the bind state sync to a player.
     *
     * This method is intentionally a no-op:
     * - State is automatically derived from inventory via V2EquipmentHelper
     * - Rendering updates are handled by event handlers
     * - The packet serves as a lightweight notification that state has changed
     */
    @Override
    @OnlyIn(Dist.CLIENT)
    protected void applySync(Player player) {
        // No-op: State is derived from inventory (synced via PacketSyncV2Equipment)
    }

    @Override
    @OnlyIn(Dist.CLIENT)
    protected void queueForRetry() {
        SyncManager.queueBindStateSync(playerUUID, stateFlags);
    }

    // Helper method
    private boolean hasFlag(byte flag) {
        return (stateFlags & flag) != 0;
    }

    // Getters for state flags

    public boolean isTiedUp() {
        return hasFlag(FLAG_TIED_UP);
    }

    public boolean isGagged() {
        return hasFlag(FLAG_GAGGED);
    }

    public boolean isBlindfolded() {
        return hasFlag(FLAG_BLINDFOLDED);
    }

    public boolean hasEarplugs() {
        return hasFlag(FLAG_HAS_EARPLUGS);
    }

    public boolean hasCollar() {
        return hasFlag(FLAG_HAS_COLLAR);
    }

    public boolean hasClothes() {
        return hasFlag(FLAG_HAS_CLOTHES);
    }

    public boolean isOnline() {
        return hasFlag(FLAG_ONLINE);
    }

    public byte getStateFlags() {
        return stateFlags;
    }
}
