/*
 *  Copyright 2025-2026 R3944Realms
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package top.r3944realms.eroticdungeongame.client.model;

import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import top.r3944realms.eroticdungeongame.content.item.WhipItem;

public class EDGArmPose {
    public static HumanoidModel.ArmPose WHIP;

    public static void init() {
        WHIP = HumanoidModel.ArmPose.create("edg_whip", false, EDGArmPose::applyWhipPose);
    }

    private static void applyWhipPose(HumanoidModel<?> model, LivingEntity entity, HumanoidArm arm) {
        if (!(entity instanceof Player player)) return;

        // 检查是否在使用鞭子
        ItemStack useItem = player.getUseItem();
        if (!(useItem.getItem() instanceof WhipItem)) return;

        // 确定使用的是哪只手
        InteractionHand useHand = player.getUsedItemHand();

        // 只有当指定的手臂是使用鞭子的手臂时才应用动画
        HumanoidArm useArm = useHand == InteractionHand.MAIN_HAND ?
                player.getMainArm() :
                (player.getMainArm() == HumanoidArm.RIGHT ? HumanoidArm.LEFT : HumanoidArm.RIGHT);

        if (arm != useArm) {
            // 非使用手臂保持正常姿势
            resetToDefaultPose(model, arm);
            return;
        }

        // 计算使用进度
        int remainedUseTime = player.getUseItemRemainingTicks();
        int maxUseTime = useItem.getUseDuration();
        float progress = 1.0f - (float)remainedUseTime / maxUseTime;
//        System.out.printf("Using %d times of %d seconds%n", remainedUseTime, maxUseTime);
        // 应用鞭子动画
        applyWhipAnimation(model, arm, progress);

        // 如果是主手，应用身体动画
        if (arm == player.getMainArm()) {
            applyBodyAnimation(model, progress, useArm);
        }
    }

    private static void resetToDefaultPose(HumanoidModel<?> model, HumanoidArm arm) {
        ModelPart armPart = getArmPart(model, arm);
        // 设置为默认手持姿势
        armPart.xRot = -0.87266463F; // 约 -50度
        armPart.yRot = 0.0F;
        armPart.zRot = 0.0F;
    }

    private static ModelPart getArmPart(HumanoidModel<?> model, HumanoidArm arm) {
        return arm == HumanoidArm.LEFT ? model.leftArm : model.rightArm;
    }

    private static void applyWhipAnimation(HumanoidModel<?> model, HumanoidArm arm, float progress) {
        ModelPart armPart = getArmPart(model, arm);
        boolean isRightArm = arm == HumanoidArm.RIGHT;

        // 完全重置旋转
        armPart.xRot = 0.0f;
        armPart.yRot = 0.0f;
        armPart.zRot = 0.0f;

        // 根据左右手决定挥舞方向
        if (isRightArm) {
            applyRightHandWhipAnimation(armPart, progress);
        } else {
            applyLeftHandWhipAnimation(armPart, progress);
        }
    }

    private static void applyRightHandWhipAnimation(ModelPart arm, float progress) {
        // 右手：从右向左挥舞（从上到下）

        if (progress < 0.2f) {
            // 阶段1：准备（向后上方拉）
            float phase = progress / 0.2f;
            arm.xRot = Mth.lerp(phase, 0.0f, -2.8f);  // 向上抬
            arm.yRot = Mth.lerp(phase, 0.0f, 0.3f);   // 先向右偏（准备从左向右）
            arm.zRot = Mth.lerp(phase, 0.0f, -0.2f);  // 手腕外旋
        }
        else if (progress < 0.5f) {
            // 阶段2：主要挥舞（从上到下，从右向左）
            float phase = (progress - 0.2f) / 0.3f;
            float swing = Mth.sin(phase * Mth.PI);

            // 手臂从上到下
            arm.xRot = -0.4f + swing * 1.2f;  // -0.4到0.8
            // 手臂从右向左摆动
            arm.yRot = 0.3f - swing * 0.6f;   // 0.3到-0.3
            // 手腕转动
            arm.zRot = -0.2f + swing * 0.3f;  // -0.2到0.1
        }
    }

    private static void applyLeftHandWhipAnimation(ModelPart arm, float progress) {
        // 左手：从左向右挥舞（从上到下）

        if (progress < 0.2f) {
            // 阶段1：准备（向后上方拉）
            float phase = progress / 0.2f;
            arm.xRot = Mth.lerp(phase, 0.0f, -2.8f);  // 向上抬
            arm.yRot = Mth.lerp(phase, 0.0f, -0.3f);  // 先向左偏（准备从右向左）
            arm.zRot = Mth.lerp(phase, 0.0f, 0.2f);   // 手腕外旋
        }
        else if (progress < 0.5f) {
            // 阶段2：主要挥舞（从上到下，从左向右）
            float phase = (progress - 0.2f) / 0.3f;
            float swing = Mth.sin(phase * Mth.PI);

            // 手臂从上到下
            arm.xRot = -0.4f + swing * 1.2f;  // -0.4到0.8
            // 手臂从左向右摆动
            arm.yRot = -0.3f + swing * 0.6f;  // -0.3到0.3
            // 手腕转动
            arm.zRot = 0.2f - swing * 0.3f;   // 0.2到-0.1
        }

    }

    private static <T extends LivingEntity> void applyBodyAnimation(HumanoidModel<T> model, float progress, HumanoidArm useArm) {
        boolean isRightHand = useArm == HumanoidArm.RIGHT;

        // 身体跟随手臂转动
        if (progress < 0.6f) {
            float phase = progress / 0.6f;
            // 根据使用的手决定身体转动方向
            if (isRightHand) {
                // 右手使用时，身体先向右转，然后向左转
                float bodyRot = Mth.sin(phase * Mth.PI) * 0.3f;  // 0到0.3到0
                model.body.yRot = bodyRot;  // 身体向右转
            } else {
                // 左手使用时，身体先向左转，然后向右转
                float bodyRot = -Mth.sin(phase * Mth.PI) * 0.3f; // 0到-0.3到0
                model.body.yRot = bodyRot;  // 身体向左转
            }
        } else {
            float phase = (progress - 0.6f) / 0.4f;
            model.body.yRot = Mth.lerp(phase, 0.0f, 0.0f);  // 回正
        }

        // 头部跟随身体转动，但幅度较小
        model.head.yRot = model.body.yRot * 0.6f;

        // 根据挥舞动作，身体会有轻微的前倾
        if (progress > 0.3f && progress < 0.7f) {
            float phase = (progress - 0.3f) / 0.4f;
            float lean = Mth.sin(phase * Mth.PI) * 0.1f;
            model.body.xRot = lean;  // 轻微前倾
        } else {
            model.body.xRot = 0.0f;
        }
    }
}