package com.tiedup.remake.client.gltf;

import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.joml.Matrix4f;

/**
 * RenderLayer that renders the glTF mesh (handcuffs) on the player.
 * Only active when enabled and only renders on the local player.
 * <p>
 * Uses the live skinning path: reads live skeleton from HumanoidModel
 * via {@link GltfLiveBoneReader}, following PlayerAnimator + bendy-lib rotations.
 * Falls back to GLB-internal skinning via {@link GltfSkinningEngine} if live reading fails.
 */
@OnlyIn(Dist.CLIENT)
public class GltfRenderLayer
    extends RenderLayer<AbstractClientPlayer, PlayerModel<AbstractClientPlayer>>
{

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

    private static final ResourceLocation CUFFS_MODEL =
        ResourceLocation.fromNamespaceAndPath(
            "tiedup",
            "models/gltf/v2/handcuffs/cuffs_prototype.glb"
        );

    public GltfRenderLayer(
        RenderLayerParent<
            AbstractClientPlayer,
            PlayerModel<AbstractClientPlayer>
        > renderer
    ) {
        super(renderer);
    }

    /**
     * The Y translate offset to place the glTF mesh in the MC PoseStack.
     * <p>
     * After LivingEntityRenderer's scale(-1,-1,1) + translate(0,-1.501,0),
     * the PoseStack origin is at the model top (1.501 blocks above feet), Y-down.
     * The glTF mesh (MC-converted) has feet at Y=0 and head at Y≈-1.5.
     * Translating by 1.501 maps glTF feet to PoseStack feet and head to top.
     */
    private static final float ALIGNMENT_Y = 1.501f;

    @Override
    public void render(
        PoseStack poseStack,
        MultiBufferSource buffer,
        int packedLight,
        AbstractClientPlayer entity,
        float limbSwing,
        float limbSwingAmount,
        float partialTick,
        float ageInTicks,
        float netHeadYaw,
        float headPitch
    ) {
        if (!GltfAnimationApplier.isEnabled()) return;
        if (entity != Minecraft.getInstance().player) return;

        GltfData data = GltfCache.get(CUFFS_MODEL);
        if (data == null) return;

        // Live path: read skeleton from HumanoidModel (after PlayerAnimator)
        PlayerModel<AbstractClientPlayer> parentModel = this.getParentModel();
        Matrix4f[] joints = GltfLiveBoneReader.computeJointMatricesFromModel(
            parentModel,
            data,
            entity
        );
        if (joints == null) {
            // Fallback to GLB-internal path if live reading fails
            joints = GltfSkinningEngine.computeJointMatrices(data);
        }

        poseStack.pushPose();

        // Align glTF mesh with MC model (feet-to-feet alignment)
        poseStack.translate(0, ALIGNMENT_Y, 0);

        GltfMeshRenderer.renderSkinned(
            data,
            joints,
            poseStack,
            buffer,
            packedLight,
            net.minecraft.client.renderer.entity.LivingEntityRenderer.getOverlayCoords(
                entity,
                0.0f
            )
        );
        poseStack.popPose();
    }
}
