package com.tiedup.remake.network.base;

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;

/**
 * Abstract base class for player sync packets (Server → Client).
 *
 * Extends AbstractClientPacket with player UUID lookup logic.
 * Used for packets that sync data for a specific player.
 *
 * Subclasses must implement:
 * - encode(FriendlyByteBuf) - serialize packet data (should call super.encodeUUID first)
 * - decode(FriendlyByteBuf) - static, deserialize packet data
 * - applySync(Player) - apply the sync to the player
 * - queueForRetry() - optional, queue for SyncManager retry if player not loaded
 */
public abstract class AbstractPlayerSyncPacket extends AbstractClientPacket {

    protected final UUID playerUUID;

    /**
     * Create a new player sync packet.
     *
     * @param playerUUID The target player's UUID
     */
    protected AbstractPlayerSyncPacket(UUID playerUUID) {
        this.playerUUID = playerUUID;
    }

    /**
     * Get the target player's UUID.
     */
    public UUID getPlayerUUID() {
        return playerUUID;
    }

    /**
     * Encode the player UUID to the buffer.
     * Subclasses should call this in their encode() method.
     *
     * @param buf The buffer to write to
     */
    protected void encodeUUID(FriendlyByteBuf buf) {
        buf.writeUUID(playerUUID);
    }

    /**
     * Decode a player UUID from the buffer.
     * Subclasses should call this in their static decode() method.
     *
     * @param buf The buffer to read from
     * @return The decoded UUID
     */
    protected static UUID decodeUUID(FriendlyByteBuf buf) {
        return buf.readUUID();
    }

    /**
     * Client-side packet handling implementation.
     * Looks up the player by UUID and calls applySync if found.
     */
    @Override
    @OnlyIn(Dist.CLIENT)
    protected void handleClientImpl() {
        if (net.minecraft.client.Minecraft.getInstance().level == null) {
            return;
        }

        Player player =
            net.minecraft.client.Minecraft.getInstance().level.getPlayerByUUID(
                playerUUID
            );
        if (player == null) {
            // Player not loaded yet - subclass may queue for retry
            queueForRetry();
            return;
        }

        applySync(player);
    }

    /**
     * Apply the sync to the target player.
     * Called when the player is found in the client world.
     *
     * @param player The target player
     */
    @OnlyIn(Dist.CLIENT)
    protected abstract void applySync(Player player);

    /**
     * Queue this packet for retry via SyncManager.
     * Called when the player is not yet loaded.
     * Default implementation does nothing (ignore).
     * Subclasses can override to queue for retry.
     */
    @OnlyIn(Dist.CLIENT)
    protected void queueForRetry() {
        // Default: do nothing (packet is non-critical or will be re-sent)
    }
}
