package com.tiedup.remake.entities.skins;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.tiedup.remake.core.TiedUpMod;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;

/**
 * Main loader for entity skins from datapacks.
 *
 * Loads skin definitions from JSON files in data/tiedup/skins/{entity_type}/*.json
 * and populates EntitySkinRegistry instances for each entity type.
 *
 * Called on server startup and /reload command via SkinReloadListener.
 *
 */
public class SkinLoader {

    private static final Gson GSON = new GsonBuilder()
        .setPrettyPrinting()
        .create();
    private static final Map<String, EntitySkinRegistry> REGISTRIES =
        new HashMap<>();

    /**
     * Entity types to load skins for.
     * Each type maps to a folder: data/tiedup/skins/{type}/*.json
     */
    private static final String[] ENTITY_TYPES = {
        "kidnapper",
        "damsel",
        "damsel_shiny",
        "kidnapper_elite",
        "kidnapper_archer",
        "kidnapper_merchant",
        "maid",
        "slave_trader",
        "labor_guard",
        "master",
    };

    /**
     * Load all skin definitions from datapacks (server-side).
     *
     * This method:
     * 1. Clears existing registries
     * 2. Scans for JSON files in data/tiedup/skins/{entity_type}/*.json
     * 3. Parses each JSON into a SkinDefinition
     * 4. Registers skins in the appropriate EntitySkinRegistry
     *
     * @param resourceManager Minecraft's resource manager (from Forge event)
     */
    public static void loadSkins(ResourceManager resourceManager) {
        TiedUpMod.LOGGER.info(
            "[SkinLoader] Starting skin loading from datapacks..."
        );
        clear();

        int totalLoaded = 0;

        for (String entityType : ENTITY_TYPES) {
            int loaded = loadSkinsForEntity(resourceManager, entityType);
            totalLoaded += loaded;
        }

        TiedUpMod.LOGGER.info(
            "[SkinLoader] Loaded {} total skins across {} entity types",
            totalLoaded,
            ENTITY_TYPES.length
        );
    }

    /**
     * Load skins for a specific entity type.
     *
     * @param resourceManager Minecraft's resource manager
     * @param entityType Entity type identifier (e.g., "kidnapper")
     * @return Number of skins loaded
     */
    private static int loadSkinsForEntity(
        ResourceManager resourceManager,
        String entityType
    ) {
        EntitySkinRegistry registry = new EntitySkinRegistry(entityType);

        // Load all JSON files from data/*/skins/{entityType}/*.json
        // Note: Minecraft searches across ALL datapacks, including tiedup's own
        String path = "skins/" + entityType;

        Map<ResourceLocation, Resource> resources =
            resourceManager.listResources(path, loc ->
                loc.getPath().endsWith(".json")
            );

        int loaded = 0;
        for (Map.Entry<
            ResourceLocation,
            Resource
        > entry : resources.entrySet()) {
            ResourceLocation location = entry.getKey();

            try (Reader reader = entry.getValue().openAsReader()) {
                JsonObject json = GSON.fromJson(reader, JsonObject.class);
                SkinDefinition skin = SkinDefinition.fromJson(json, entityType);
                registry.register(skin);
                loaded++;
            } catch (Exception e) {
                TiedUpMod.LOGGER.error(
                    "[SkinLoader] Failed to load skin from {}: {}",
                    location,
                    e.getMessage()
                );
                TiedUpMod.LOGGER.debug("[SkinLoader] Exception details:", e);
            }
        }

        REGISTRIES.put(entityType, registry);

        if (loaded > 0) {
            TiedUpMod.LOGGER.info(
                "[SkinLoader] Loaded {} skins for entity type '{}'",
                loaded,
                entityType
            );
        } else {
            TiedUpMod.LOGGER.warn(
                "[SkinLoader] No skins found for entity type '{}' (will use hardcoded fallback)",
                entityType
            );
        }

        return loaded;
    }

    /**
     * Get the skin registry for a specific entity type.
     *
     * If no registry exists yet, creates an empty one.
     *
     * @param entityType Entity type identifier
     * @return EntitySkinRegistry for this type
     */
    public static EntitySkinRegistry getRegistry(String entityType) {
        return REGISTRIES.computeIfAbsent(entityType, EntitySkinRegistry::new);
    }

    /**
     * Clear all registries.
     *
     * Called before reloading to ensure fresh data.
     */
    public static void clear() {
        REGISTRIES.values().forEach(EntitySkinRegistry::clear);
        REGISTRIES.clear();
        TiedUpMod.LOGGER.debug("[SkinLoader] Cleared all skin registries");
    }

    /**
     * Get the number of registered entity types.
     *
     * @return Number of entity types with skin registries
     */
    public static int getRegistryCount() {
        return REGISTRIES.size();
    }

    /**
     * Check if any skins are loaded for a given entity type.
     *
     * @param entityType Entity type identifier
     * @return true if at least one skin is loaded
     */
    public static boolean hasSkinsForType(String entityType) {
        EntitySkinRegistry registry = REGISTRIES.get(entityType);
        return registry != null && registry.count() > 0;
    }
}
