package com.tiedup.remake.mixin.client;

import dev.kosmx.playerAnim.api.layered.AnimationStack;
import dev.kosmx.playerAnim.api.layered.IAnimation;
import dev.kosmx.playerAnim.impl.IAnimatedPlayer;
import dev.kosmx.playerAnim.impl.animation.AnimationApplier;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.resources.ResourceLocation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

/**
 * Mixin to inject IAnimatedPlayer support into MCA villagers.
 *
 * <p>This allows MCA villagers to use PlayerAnimator animations for bondage poses,
 * instead of just static pose rotations.
 *
 * <p>Uses @Pseudo annotation - mixin is optional and will be skipped if MCA is not installed.
 *
 * <p>Target class: net.mca.entity.VillagerEntityMCA
 */
@Pseudo
@Mixin(targets = "forge.net.mca.entity.VillagerEntityMCA", remap = false)
public abstract class MixinVillagerEntityMCAAnimated
    implements IAnimatedPlayer
{

    /**
     * Animation stack for layered animations.
     */
    @Unique
    private AnimationStack tiedup$animationStack;

    /**
     * Animation applier for applying animations to model parts.
     */
    @Unique
    private AnimationApplier tiedup$animationApplier;

    /**
     * Storage for named animations.
     */
    @Unique
    private final Map<ResourceLocation, IAnimation> tiedup$storedAnimations =
        new HashMap<>();

    /**
     * Track if animation system has been initialized.
     */
    @Unique
    private boolean tiedup$animInitialized = false;

    /**
     * Initialize animation system after entity construction.
     */
    @Inject(method = "<init>*", at = @At("RETURN"), remap = false)
    private void tiedup$initAnimations(CallbackInfo ci) {
        tiedup$ensureAnimationInit();
    }

    /**
     * Lazy initialization of animation system.
     * Called on first access to ensure system is ready.
     * Only initializes on CLIENT side!
     */
    @Unique
    private void tiedup$ensureAnimationInit() {
        if (!tiedup$animInitialized) {
            // Only create animation stack on client side
            net.minecraft.world.entity.LivingEntity self =
                (net.minecraft.world.entity.LivingEntity) (Object) this;
            if (self.level() == null || !self.level().isClientSide()) {
                return; // Don't initialize on server
            }

            this.tiedup$animationStack = new AnimationStack();
            this.tiedup$animationApplier = new AnimationApplier(
                this.tiedup$animationStack
            );
            tiedup$animInitialized = true;
        }
    }

    // IAnimatedPlayer Implementation

    @Override
    public AnimationStack getAnimationStack() {
        tiedup$ensureAnimationInit();
        return this.tiedup$animationStack;
    }

    @Override
    public AnimationApplier playerAnimator_getAnimation() {
        tiedup$ensureAnimationInit();
        return this.tiedup$animationApplier;
    }

    @Override
    public IAnimation playerAnimator_getAnimation(ResourceLocation id) {
        return this.tiedup$storedAnimations.get(id);
    }

    @Override
    public IAnimation playerAnimator_setAnimation(
        ResourceLocation id,
        IAnimation animation
    ) {
        if (animation == null) {
            return this.tiedup$storedAnimations.remove(id);
        } else {
            return this.tiedup$storedAnimations.put(id, animation);
        }
    }
}
