package xyz.illuc.neuralgiacore.mixin.Tfc;

import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import net.adinvas.prototype_pain.PlayerHealthProvider;
import net.dries007.tfc.common.capabilities.food.FoodData;
import net.dries007.tfc.common.capabilities.food.Nutrient;
import net.dries007.tfc.common.capabilities.food.TFCFoodData;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.player.Abilities;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import xyz.illuc.neuralgiacore.interfaces.IPlayerHealthDataAccessor;

@Mixin(TFCFoodData.class)
public class MixinFoodData {
    @Shadow private float thirst;

    @Shadow @Final private Player sourcePlayer;

    @Redirect(method = "tick", at = @At(
            value = "INVOKE",
            target = "Lnet/minecraft/world/entity/player/Player;getAbilities()Lnet/minecraft/world/entity/player/Abilities;")
    )
    private Abilities redir(Player instance){

        return null;
    }

    @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;tick(Lnet/minecraft/world/entity/player/Player;)V", shift = At.Shift.AFTER))
    private void injected(Player player, CallbackInfo ci, @Local LocalRef<Difficulty> difficulty) {
        difficulty.set(Difficulty.PEACEFUL); //Disables the default thirst debuffs
    }

    @Inject(method = "eat(Lnet/dries007/tfc/common/capabilities/food/FoodData;)V", at = @At(value = "HEAD"), remap = false)
    private void modifySickness(CallbackInfo ci, @Local FoodData data) {
        net.minecraft.world.food.FoodData nutrition = this.sourcePlayer.getFoodData();

        if (nutrition instanceof TFCFoodData) {
            TFCFoodData tfcNutrition = (TFCFoodData) nutrition;

            float grains = tfcNutrition.getNutrition().getNutrient(Nutrient.GRAIN);
            float vegetables = tfcNutrition.getNutrition().getNutrient(Nutrient.VEGETABLES);
            float fruit = tfcNutrition.getNutrition().getNutrient(Nutrient.FRUIT);
            float protein = tfcNutrition.getNutrition().getNutrient(Nutrient.PROTEIN);
            float dairy = tfcNutrition.getNutrition().getNutrient(Nutrient.DAIRY);

            int deficientCount = 0;
            float totalDeficiency = 0;

            if (grains < 0.1f) {
                deficientCount++;
                totalDeficiency += (0.1f - grains);
            }
            if (vegetables < 0.1f) {
                deficientCount++;
                totalDeficiency += (0.1f - vegetables);
            }
            if (fruit < 0.1f) {
                deficientCount++;
                totalDeficiency += (0.1f - fruit);
            }
            if (protein < 0.1f) {
                deficientCount++;
                totalDeficiency += (0.1f - protein);
            }
            if (dairy < 0.1f) {
                deficientCount++;
                totalDeficiency += (0.1f - dairy);
            }

            float totalSicknessToAdd = 0;

            // add sickness from nutrient deficiency
            if (deficientCount > 0) {
                float deficiencySickness = (deficientCount * 2.0f) + (totalDeficiency * 10.0f);
                deficiencySickness = Math.min(deficiencySickness, 8.0f);
                totalSicknessToAdd += deficiencySickness;
            }

            // add sickness from imbalance
            float average = (grains + vegetables + fruit + protein + dairy) / 5.0f;

            float imbalance = 0;
            imbalance += (float) Math.pow(grains - average, 2);
            imbalance += (float) Math.pow(vegetables - average, 2);
            imbalance += (float) Math.pow(fruit - average, 2);
            imbalance += (float) Math.pow(protein - average, 2);
            imbalance += (float) Math.pow(dairy - average, 2);

            float stdDev = (float) Math.sqrt(imbalance / 5.0f);


            if (stdDev > 0.25f) {
                float imbalanceSickness = (stdDev - 0.25f) * 16.7f;
                imbalanceSickness = Math.min(imbalanceSickness, 5.0f);
                totalSicknessToAdd += imbalanceSickness*100;
            }

            if (totalSicknessToAdd > 0) {
                totalSicknessToAdd = Math.min(totalSicknessToAdd, 10.0f);

                float finalSicknessToAdd = totalSicknessToAdd;
                this.sourcePlayer.getCapability(PlayerHealthProvider.PLAYER_HEALTH_DATA).ifPresent(h -> {
                    IPlayerHealthDataAccessor accessor = (IPlayerHealthDataAccessor) h;
                    float currentSickness = accessor.getSickness();
                    accessor.setSickness(Math.max(0, Math.min(100, currentSickness + finalSicknessToAdd)));
                });
            }
        }
    }

}
