package com.tiedup.remake.entities.armorstand;

import com.tiedup.remake.v2.BodyRegionV2;
import java.util.EnumMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

/**
 * Client-side cache for armor stand bondage data.
 *
 * Since getPersistentData() is not synced to clients, we use this cache
 * to store bondage item data received via network packets.
 */
@OnlyIn(Dist.CLIENT)
public class ArmorStandBondageClientCache {

    /**
     * Cache mapping entity ID to bondage data.
     */
    private static final Map<Integer, BondageData> CACHE =
        new ConcurrentHashMap<>();

    /**
     * Data holder for an armor stand's bondage items.
     * Uses an EnumMap keyed by BodyRegionV2.
     */
    public static class BondageData {

        private final EnumMap<BodyRegionV2, ItemStack> items = new EnumMap<>(
            BodyRegionV2.class
        );

        public ItemStack getItem(BodyRegionV2 region) {
            return items.getOrDefault(region, ItemStack.EMPTY);
        }

        public void setItem(BodyRegionV2 region, ItemStack stack) {
            if (stack == null || stack.isEmpty()) {
                items.remove(region);
            } else {
                items.put(region, stack);
            }
        }

        public boolean hasAnyItems() {
            return !items.isEmpty();
        }
    }

    /**
     * Get bondage data for an entity.
     *
     * @param entityId The entity ID
     * @return The bondage data, or null if none cached
     */
    public static BondageData getData(int entityId) {
        return CACHE.get(entityId);
    }

    /**
     * Get or create bondage data for an entity.
     *
     * @param entityId The entity ID
     * @return The bondage data
     */
    public static BondageData getOrCreateData(int entityId) {
        return CACHE.computeIfAbsent(entityId, id -> new BondageData());
    }

    /**
     * Update a specific item in the cache.
     *
     * @param entityId The entity ID
     * @param region The body region
     * @param stack The item stack
     */
    public static void updateItem(
        int entityId,
        BodyRegionV2 region,
        ItemStack stack
    ) {
        BondageData data = getOrCreateData(entityId);
        data.setItem(region, stack);

        // Clean up empty entries
        if (!data.hasAnyItems()) {
            CACHE.remove(entityId);
        }
    }

    /**
     * Check if an armor stand has any bondage items cached.
     *
     * @param entityId The entity ID
     * @return True if any items are cached
     */
    public static boolean hasItems(int entityId) {
        BondageData data = CACHE.get(entityId);
        return data != null && data.hasAnyItems();
    }

    /**
     * Get an item from the cache.
     *
     * @param entityId The entity ID
     * @param region The body region
     * @return The item, or empty if none
     */
    public static ItemStack getItem(int entityId, BodyRegionV2 region) {
        BondageData data = CACHE.get(entityId);
        if (data == null) {
            return ItemStack.EMPTY;
        }
        return data.getItem(region);
    }

    /**
     * Remove cached data for an entity.
     *
     * @param entityId The entity ID
     */
    public static void remove(int entityId) {
        CACHE.remove(entityId);
    }

    /**
     * Clear all cached data.
     * Should be called when leaving a world.
     */
    public static void clear() {
        CACHE.clear();
    }
}
