package com.tiedup.remake.client.gltf;

import com.tiedup.remake.client.animation.context.ContextAnimationFactory;
import com.tiedup.remake.client.animation.context.ContextGlbRegistry;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RegisterClientReloadListenersEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * MOD-bus setup for the generic glTF pipeline — init + cache-invalidation
 * reload listener. Bondage-specific registrations (render layer, item-aware
 * reload listeners) live in {@code V2ClientSetup}.
 */
public final class GltfClientSetup {

    private static final Logger LOGGER = LogManager.getLogger("GltfPipeline");

    private GltfClientSetup() {}

    @Mod.EventBusSubscriber(
        modid = "tiedup",
        bus = Mod.EventBusSubscriber.Bus.MOD,
        value = Dist.CLIENT
    )
    public static class ModBusEvents {

        @SubscribeEvent
        public static void onClientSetup(FMLClientSetupEvent event) {
            event.enqueueWork(() -> {
                GltfCache.init();
                GltfAnimationApplier.init();
                LOGGER.info("[GltfPipeline] Client setup complete");
            });
        }

        /**
         * Register the generic GLB cache-clear reload listener.
         *
         * <p>{@code HIGH} priority so it fires before any downstream
         * listener that consumes GLB state. Within this single {@code apply}
         * block, the sub-order matters:</p>
         * <ol>
         *   <li>Drop the three mutually-independent byte caches
         *       ({@code GltfCache}, {@code GltfAnimationApplier.invalidateCache},
         *       {@code GltfMeshRenderer.clearRenderTypeCache}).</li>
         *   <li>Reload {@code ContextGlbRegistry} before clearing
         *       {@code ContextAnimationFactory.clearCache()} — otherwise
         *       the next factory lookup rebuilds clips against the stale
         *       registry and caches the wrong data.</li>
         *   <li>Clear {@code FurnitureGltfCache} last.</li>
         * </ol>
         *
         * <p>Bondage-specific listeners register at {@code LOW} priority from
         * {@code V2ClientSetup.onRegisterReloadListeners}, so the cache-clear
         * here is guaranteed to land first.</p>
         */
        @SubscribeEvent(priority = EventPriority.HIGH)
        public static void onRegisterReloadListeners(
            RegisterClientReloadListenersEvent event
        ) {
            event.registerReloadListener(
                new SimplePreparableReloadListener<Void>() {
                    @Override
                    protected Void prepare(
                        ResourceManager resourceManager,
                        ProfilerFiller profiler
                    ) {
                        return null;
                    }

                    @Override
                    protected void apply(
                        Void nothing,
                        ResourceManager resourceManager,
                        ProfilerFiller profiler
                    ) {
                        GltfCache.clearCache();
                        GltfAnimationApplier.invalidateCache();
                        GltfMeshRenderer.clearRenderTypeCache();
                        ContextGlbRegistry.reload(resourceManager);
                        ContextAnimationFactory.clearCache();
                        com.tiedup.remake.v2.furniture.client.FurnitureGltfCache.clear();
                        LOGGER.info(
                            "[GltfPipeline] Caches cleared on resource reload"
                        );
                    }
                }
            );
        }
    }

    /** FORGE bus event subscribers (client-side commands). */
    @Mod.EventBusSubscriber(
        modid = "tiedup",
        bus = Mod.EventBusSubscriber.Bus.FORGE,
        value = Dist.CLIENT
    )
    public static class ForgeBusEvents {

        @SubscribeEvent
        public static void onRegisterClientCommands(
            net.minecraftforge.client.event.RegisterClientCommandsEvent event
        ) {
            com.tiedup.remake.commands.ValidateGlbCommand.register(
                event.getDispatcher()
            );
            LOGGER.info(
                "[GltfPipeline] Client command /tiedup validate registered"
            );
        }
    }
}
