package com.tiedup.remake.v2.client;

import com.tiedup.remake.blocks.entity.ModBlockEntities;
import com.tiedup.remake.client.model.CellCoreBakedModel;
import com.tiedup.remake.client.renderer.CellCoreRenderer;
import com.tiedup.remake.core.TiedUpMod;
import com.tiedup.remake.v2.V2BlockEntities;
import java.util.Map;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

/**
 * V2 Client-side setup.
 * Registers block entity renderers, model replacements, and icon model overrides.
 *
 * <p>The icon override system allows data-driven bondage items and furniture placers
 * to display per-variant inventory sprites. Each JSON definition can specify an
 * optional {@code icon} field pointing to a model ResourceLocation. The model
 * is resolved at render time from the baked model registry.</p>
 *
 * <p>Icon models that correspond to existing registered items (e.g., "tiedup:item/armbinder")
 * are automatically available. For custom icon models that don't correspond to a registered
 * item, place the model JSON under {@code assets/<namespace>/models/item/icons/} and it
 * will be registered for baking via {@link ModelEvent.RegisterAdditional}.</p>
 */
@Mod.EventBusSubscriber(
    modid = TiedUpMod.MOD_ID,
    bus = Mod.EventBusSubscriber.Bus.MOD,
    value = Dist.CLIENT
)
public class V2ClientSetup {

    @SubscribeEvent
    public static void registerRenderers(
        EntityRenderersEvent.RegisterRenderers event
    ) {
        // Register OBJ block renderers
        event.registerBlockEntityRenderer(
            V2BlockEntities.PET_BOWL.get(),
            ObjBlockRenderer::new
        );
        event.registerBlockEntityRenderer(
            V2BlockEntities.PET_BED.get(),
            ObjBlockRenderer::new
        );
        event.registerBlockEntityRenderer(
            V2BlockEntities.PET_CAGE.get(),
            ObjBlockRenderer::new
        );

        // Register Cell Core pulsing indicator renderer
        event.registerBlockEntityRenderer(
            ModBlockEntities.CELL_CORE.get(),
            CellCoreRenderer::new
        );

        TiedUpMod.LOGGER.info(
            "[V2ClientSetup] Registered block entity renderers"
        );
    }

    @SubscribeEvent
    public static void onModifyBakingResult(
        ModelEvent.ModifyBakingResult event
    ) {
        // Block model path key (used in model JSON references)
        ResourceLocation blockModelLoc = ResourceLocation.fromNamespaceAndPath(
            TiedUpMod.MOD_ID,
            "block/cell_core"
        );
        // Blockstate variant key (used by the block renderer to look up models)
        ModelResourceLocation stateModelLoc = new ModelResourceLocation(
            ResourceLocation.fromNamespaceAndPath(
                TiedUpMod.MOD_ID,
                "cell_core"
            ),
            ""
        );

        // Find the original model from either key
        BakedModel original = event.getModels().get(stateModelLoc);
        if (original == null) {
            original = event.getModels().get(blockModelLoc);
        }

        if (original != null) {
            CellCoreBakedModel wrapper = new CellCoreBakedModel(original);
            event.getModels().put(blockModelLoc, wrapper);
            event.getModels().put(stateModelLoc, wrapper);
            TiedUpMod.LOGGER.info(
                "[V2ClientSetup] Replaced cell_core BakedModel at both model keys"
            );
        }

        // ===== Data-driven item icon overrides =====
        wrapItemModelWithIconOverrides(
            event.getModels(),
            "data_driven_item",
            DataDrivenIconOverrides.Mode.BONDAGE_ITEM
        );

        wrapItemModelWithIconOverrides(
            event.getModels(),
            "furniture_placer",
            DataDrivenIconOverrides.Mode.FURNITURE_PLACER
        );
    }

    /**
     * Wrap an item's baked model with a {@link DataDrivenIconBakedModel} that
     * switches the rendered model based on NBT icon definitions.
     *
     * @param models   the mutable model registry from {@link ModelEvent.ModifyBakingResult}
     * @param itemName the item registry name (e.g., "data_driven_item")
     * @param mode     the icon override mode (determines which NBT key to read)
     */
    private static void wrapItemModelWithIconOverrides(
        Map<ResourceLocation, BakedModel> models,
        String itemName,
        DataDrivenIconOverrides.Mode mode
    ) {
        ModelResourceLocation itemModelLoc = new ModelResourceLocation(
            new ResourceLocation(TiedUpMod.MOD_ID, itemName),
            "inventory"
        );

        BakedModel originalItemModel = models.get(itemModelLoc);
        if (originalItemModel == null) {
            TiedUpMod.LOGGER.warn(
                "[V2ClientSetup] Could not find baked model for {} — icon overrides not applied",
                itemModelLoc
            );
            return;
        }

        DataDrivenIconOverrides overrides = new DataDrivenIconOverrides(mode);
        DataDrivenIconBakedModel wrapped = new DataDrivenIconBakedModel(
            originalItemModel,
            overrides
        );
        models.put(itemModelLoc, wrapped);

        TiedUpMod.LOGGER.info(
            "[V2ClientSetup] Wrapped {} model with icon overrides (mode={})",
            itemName,
            mode
        );
    }
}
