package xyz.illuc.neuralgiacore.mixin.PrototypePain;

import net.adinvas.prototype_pain.PlayerHealthProvider;
import net.adinvas.prototype_pain.limbs.Limb;
import net.adinvas.prototype_pain.network.LegUsePacket;
import net.dries007.tfc.common.entities.TFCEntities;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.network.NetworkEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Unique;

import java.util.function.Supplier;

@Mixin(LegUsePacket.class)
public class MixinLegUsePacket {
    /**
     * @author
     * @reason
     */
    @Overwrite(remap = false)
    public void handle(Supplier<NetworkEvent.Context> ctx){
        ctx.get().enqueueWork(() -> {
            ServerPlayer player = ctx.get().getSender();
            if (player != null) {
                tfcpain$onLegUse(player);
            }

        });
        ctx.get().setPacketHandled(true);
    }

    @Unique
    private void tfcpain$onLegUse(Player player) {
        player.getCapability(PlayerHealthProvider.PLAYER_HEALTH_DATA).ifPresent(playerHealthData -> {

            float pain_per_tick = 0.4F * (player.isVisuallyCrawling() ? 0.1F: 1) * (player.isSprinting() ? 1.5F: 1) * (player.isCrouching() ? 0.5F: 1);

            if (player.isPassenger()) {
                if((player.getVehicle().getType() == TFCEntities.HORSE.get()) && (player.getVehicle().getType() == TFCEntities.DONKEY.get()) && (player.getVehicle().getType() == TFCEntities.MULE.get()))
                    pain_per_tick = 0.3F;
                else
                    pain_per_tick = 0.0F;
            }



            if (pain_per_tick != 0.0F) {

                if (!canSupport(player.getOffhandItem())) {

                    float rightLegDamage =
                            playerHealthData.getLimbFracture(Limb.RIGHT_LEG) +
                                    playerHealthData.getLimbDislocated(Limb.RIGHT_LEG);

                    if (rightLegDamage > 0.0F) {
                        playerHealthData.applyPain(
                                Limb.RIGHT_LEG,
                                painFromDamage(pain_per_tick * (playerHealthData.hasLimbSplint(Limb.RIGHT_LEG) ? 0.5F: 1), rightLegDamage)
                        );
                    }

                    float rightFootDamage =
                            playerHealthData.getLimbFracture(Limb.RIGHT_FOOT) +
                                    playerHealthData.getLimbDislocated(Limb.RIGHT_FOOT);

                    if (rightFootDamage > 0.0F) {
                        playerHealthData.applyPain(
                                Limb.RIGHT_FOOT,
                                painFromDamage(pain_per_tick * (playerHealthData.hasLimbSplint(Limb.RIGHT_FOOT) ? 0.5F: 1), rightFootDamage)
                        );
                    }
                }

                if (!canSupport(player.getMainHandItem())) {

                    float leftLegDamage =
                            playerHealthData.getLimbFracture(Limb.LEFT_LEG) +
                                    playerHealthData.getLimbDislocated(Limb.LEFT_LEG);

                    if (leftLegDamage > 0.0F) {
                        playerHealthData.applyPain(
                                Limb.LEFT_LEG,
                                painFromDamage(pain_per_tick * (playerHealthData.hasLimbSplint(Limb.LEFT_LEG) ? 0.5F: 1), leftLegDamage)
                        );
                    }

                    float leftFootDamage =
                            playerHealthData.getLimbFracture(Limb.LEFT_FOOT) +
                                    playerHealthData.getLimbDislocated(Limb.LEFT_FOOT);

                    if (leftFootDamage > 0.0F) {
                        playerHealthData.applyPain(
                                Limb.LEFT_FOOT,
                                painFromDamage(pain_per_tick * (playerHealthData.hasLimbSplint(Limb.LEFT_FOOT) ? 0.5F: 1), leftFootDamage)
                        );
                    }
                }
            }


        });
    }

    @Unique
    private static float painFromDamage(float basePain, float damage) {
        if (damage <= 0.0F) return 0.0F;

        final float K = 1.25F;
        return basePain * (1.0F - (float) Math.exp(-K * damage));
    }

    @Unique
    private boolean canSupport(ItemStack item){
        return item.getItem().toString().equals("refined_walking_cane") || item.getItem().toString().equals("walking_cane") ;
    }
}
