package com.tiedup.remake.v2.furniture.network;

import com.tiedup.remake.network.ModNetwork;
import com.tiedup.remake.v2.furniture.EntityFurniture;
import java.util.function.Supplier;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.NetworkEvent;

/**
 * Server-to-client packet that syncs a furniture entity's lock bitmask and
 * animation state.
 *
 * <p>While {@link EntityFurniture} uses {@code SynchedEntityData} for these
 * fields (which handles baseline sync), this packet provides an immediate,
 * explicit update when the server modifies lock state or animation state
 * (e.g., after a lock toggle interaction or a struggle minigame state change).
 * SynchedEntityData batches dirty entries once per tick, so this packet
 * ensures clients see the change within the same network flush.</p>
 *
 * <p>Wire format (6 bytes): int entityId (4) + byte lockBits (1) + byte animState (1)</p>
 *
 * <p>Direction: Server to Client (S2C)</p>
 */
public class PacketSyncFurnitureState {

    private final int entityId;
    private final byte lockBits;
    private final byte animState;

    public PacketSyncFurnitureState(
        int entityId,
        byte lockBits,
        byte animState
    ) {
        this.entityId = entityId;
        this.lockBits = lockBits;
        this.animState = animState;
    }

    // ==================== Codec ====================

    public static void encode(
        PacketSyncFurnitureState msg,
        FriendlyByteBuf buf
    ) {
        buf.writeInt(msg.entityId);
        buf.writeByte(msg.lockBits);
        buf.writeByte(msg.animState);
    }

    public static PacketSyncFurnitureState decode(FriendlyByteBuf buf) {
        return new PacketSyncFurnitureState(
            buf.readInt(),
            buf.readByte(),
            buf.readByte()
        );
    }

    // ==================== Handler ====================

    public static void handle(
        PacketSyncFurnitureState msg,
        Supplier<NetworkEvent.Context> ctxSupplier
    ) {
        NetworkEvent.Context ctx = ctxSupplier.get();
        ctx.enqueueWork(() -> {
            if (FMLEnvironment.dist == Dist.CLIENT) {
                handleOnClient(msg);
            }
        });
        ctx.setPacketHandled(true);
    }

    @OnlyIn(Dist.CLIENT)
    private static void handleOnClient(PacketSyncFurnitureState msg) {
        Level level = Minecraft.getInstance().level;
        if (level == null) return;

        Entity entity = level.getEntity(msg.entityId);
        if (entity instanceof EntityFurniture furniture) {
            furniture.setSeatLockBitsRaw(msg.lockBits);
            furniture.setAnimState(msg.animState);
        }
    }

    // ==================== Server-side Helper ====================

    /**
     * Send the current lock + anim state of the given furniture entity to all
     * players tracking it. Call this from the server after modifying lock bits
     * or animation state.
     *
     * @param furniture the furniture entity whose state changed (must be server-side)
     */
    public static void sendToTracking(EntityFurniture furniture) {
        ModNetwork.sendToTracking(
            new PacketSyncFurnitureState(
                furniture.getId(),
                furniture.getSeatLockBits(),
                furniture.getAnimState()
            ),
            furniture
        );
    }
}
