package dev.crucifixbeta.mod.modules.impl.player;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.ClientTickEvent;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.api.utils.math.Timer;
import dev.crucifixbeta.api.utils.player.EntityUtil;
import dev.crucifixbeta.api.utils.player.InventoryUtil;
import dev.crucifixbeta.api.utils.world.BlockPosX;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.settings.impl.BindSetting;
import dev.crucifixbeta.mod.modules.settings.impl.BooleanSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.PotionContentsComponent;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket;
import net.minecraft.util.Hand;

@Environment(EnvType.CLIENT)
public class AutoPot extends Module {
   public static AutoPot INSTANCE;
   private final SliderSetting delay = this.add(new SliderSetting("Delay", 0.2, 0.0, 10.0, 0.1).setSuffix("s"));
   private final SliderSetting prePotTime = this.add(new SliderSetting("PrePotTime", 0.5, 0.0, 1.0, 0.01).setSuffix("s"));
   private final BooleanSetting speed = this.add(new BooleanSetting("Speed", true));
   private final BooleanSetting resistance = this.add(new BooleanSetting("Resistance", true));
   private final BooleanSetting strength = this.add(new BooleanSetting("Strength", true));
   private final BooleanSetting slowFalling = this.add(new BooleanSetting("SlowFalling", false));
   private final BooleanSetting usingPause = this.add(new BooleanSetting("UsingPause", false));
   private final BooleanSetting onlyGround = this.add(new BooleanSetting("OnlyGround", true));
   private final BooleanSetting inventory = this.add(new BooleanSetting("InventorySwap", true));
   private final BindSetting speedKey = this.add(new BindSetting("SpeedKey", -1));
   private final BindSetting strengthKey = this.add(new BindSetting("StrengthKey", -1));
   private final BindSetting resistanceKey = this.add(new BindSetting("ResistanceKey", -1));
   private final Timer delayTimer = new Timer();
   private boolean throwing = false;
   private boolean turtlePress;
   private boolean speedPress;
   private boolean strengthPress;

   public AutoPot() {
      super("AutoPot", Module.Category.Player);
      this.setChinese("\u81ea\u52a8\u836f\u6c34");
      INSTANCE = this;
      CrucifixBeta.EVENT_BUS.subscribe(new AutoPot.AutoPotTick());
   }

   public static int findPotionInventorySlot(StatusEffect targetEffect) {
      for (int var1 = 35; var1 >= 0; var1--) {
         ItemStack var2 = mc.player.getInventory().getStack(var1);
         if (Item.getRawId(var2.getItem()) == Item.getRawId(Items.SPLASH_POTION)) {
            PotionContentsComponent var3 = var2.getOrDefault(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT);

            for (StatusEffectInstance var5 : var3.getEffects()) {
               if (var5.getEffectType().value() == targetEffect) {
                  return var1 < 9 ? var1 + 36 : var1;
               }
            }
         }
      }

      return -1;
   }

   public static int findPotion(StatusEffect targetEffect) {
      for (int var1 = 0; var1 < 9; var1++) {
         ItemStack var2 = mc.player.getInventory().getStack(var1);
         if (Item.getRawId(var2.getItem()) == Item.getRawId(Items.SPLASH_POTION)) {
            PotionContentsComponent var3 = var2.getOrDefault(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT);

            for (StatusEffectInstance var5 : var3.getEffects()) {
               if (var5.getEffectType().value() == targetEffect) {
                  return var1;
               }
            }
         }
      }

      return -1;
   }

   @Override
   public void onDisable() {
      this.throwing = false;
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if (!this.inventory.getValue() || EntityUtil.inInventory()) {
         if (this.delayTimer.passedMs(this.delay.getValue() * 1000.0)) {
            if (!this.onlyGround.getValue()
               || (mc.player.isOnGround() || CrucifixBeta.PLAYER.isInWeb(mc.player)) && !mc.world.isAir(new BlockPosX(mc.player.getPos().add(0.0, -1.0, 0.0)))) {
               if (this.resistance.getValue()) {
                  boolean var2 = false;
                  StatusEffectInstance var3 = mc.player.getStatusEffect(StatusEffects.RESISTANCE);
                  if (var3 == null) {
                     var2 = true;
                  } else if (var3.getAmplifier() < 2) {
                     var2 = true;
                  } else if ((double)var3.getDuration() / 20.0 < this.prePotTime.getValue()) {
                     var2 = true;
                  }

                  if (var2) {
                     this.throwing = this.checkThrow(StatusEffects.RESISTANCE.value());
                     if (this.isThrow()) {
                        this.throwPotion(StatusEffects.RESISTANCE.value());
                        return;
                     }
                  }
               }

               if (this.speed.getValue()) {
                  boolean var4 = false;
                  StatusEffectInstance var7 = mc.player.getStatusEffect(StatusEffects.SPEED);
                  if (var7 == null) {
                     var4 = true;
                  } else if ((double)var7.getDuration() / 20.0 < this.prePotTime.getValue()) {
                     var4 = true;
                  }

                  if (var4) {
                     this.throwing = this.checkThrow(StatusEffects.SPEED.value());
                     if (this.isThrow()) {
                        this.throwPotion(StatusEffects.SPEED.value());
                        return;
                     }
                  }
               }

               if (this.strength.getValue()) {
                  boolean var5 = false;
                  StatusEffectInstance var8 = mc.player.getStatusEffect(StatusEffects.STRENGTH);
                  if (var8 == null) {
                     var5 = true;
                  } else if ((double)var8.getDuration() / 20.0 < this.prePotTime.getValue()) {
                     var5 = true;
                  }

                  if (var5) {
                     this.throwing = this.checkThrow(StatusEffects.STRENGTH.value());
                     if (this.isThrow()) {
                        this.throwPotion(StatusEffects.STRENGTH.value());
                        return;
                     }
                  }
               }

               if (this.slowFalling.getValue()) {
                  boolean var6 = false;
                  StatusEffectInstance var9 = mc.player.getStatusEffect(StatusEffects.SLOW_FALLING);
                  if (var9 == null) {
                     var6 = true;
                  } else if ((double)var9.getDuration() / 20.0 < this.prePotTime.getValue()) {
                     var6 = true;
                  }

                  if (var6) {
                     this.throwing = this.checkThrow(StatusEffects.SLOW_FALLING.value());
                     if (this.isThrow()) {
                        this.throwPotion(StatusEffects.SLOW_FALLING.value());
                     }
                  }
               }
            }
         }
      }
   }

   public void throwPotion(StatusEffect targetEffect) {
      int var2 = mc.player.getInventory().selectedSlot;
      int var3;
      if (this.inventory.getValue() && (var3 = findPotionInventorySlot(targetEffect)) != -1) {
         CrucifixBeta.ROTATION.snapAt(CrucifixBeta.ROTATION.rotationYaw, 90.0F);
         InventoryUtil.inventorySwap(var3, mc.player.getInventory().selectedSlot);
         sendSequencedPacket(
            id -> new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, id, CrucifixBeta.ROTATION.getLastYaw(), CrucifixBeta.ROTATION.getLastPitch())
         );
         InventoryUtil.inventorySwap(var3, mc.player.getInventory().selectedSlot);
         EntityUtil.syncInventory();
         CrucifixBeta.ROTATION.snapBack();
         this.delayTimer.reset();
      } else {
         var3 = findPotion(targetEffect);
         if (var3 != -1) {
            CrucifixBeta.ROTATION.snapAt(CrucifixBeta.ROTATION.rotationYaw, 90.0F);
            InventoryUtil.switchToSlot(var3);
            sendSequencedPacket(
               id -> new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, id, CrucifixBeta.ROTATION.getLastYaw(), CrucifixBeta.ROTATION.getLastPitch())
            );
            InventoryUtil.switchToSlot(var2);
            CrucifixBeta.ROTATION.snapBack();
            this.delayTimer.reset();
         }
      }
   }

   public boolean isThrow() {
      return this.throwing;
   }

   public boolean checkThrow(StatusEffect targetEffect) {
      if (!EntityUtil.inInventory()) {
         return false;
      } else {
         return this.usingPause.getValue() && mc.player.isUsingItem()
            ? false
            : findPotion(targetEffect) != -1 || this.inventory.getValue() && findPotionInventorySlot(targetEffect) != -1;
      }
   }
@Environment(EnvType.CLIENT)
   public class AutoPotTick {
      @EventListener
      public void onTick(ClientTickEvent event) {
         if (!Module.nullCheck() && !event.isPost()) {
            if (!AutoPot.this.inventory.getValue() || EntityUtil.inInventory()) {
               if (Wrapper.mc.currentScreen == null) {
                  if (AutoPot.this.resistanceKey.isPressed()) {
                     if (!AutoPot.this.turtlePress && AutoPot.this.checkThrow(StatusEffects.RESISTANCE.value())) {
                        AutoPot.this.throwPotion(StatusEffects.RESISTANCE.value());
                        AutoPot.this.turtlePress = true;
                        return;
                     }
                  } else {
                     AutoPot.this.turtlePress = false;
                  }

                  if (AutoPot.this.strengthKey.isPressed()) {
                     if (!AutoPot.this.strengthPress && AutoPot.this.checkThrow(StatusEffects.STRENGTH.value())) {
                        AutoPot.this.throwPotion(StatusEffects.STRENGTH.value());
                        AutoPot.this.strengthPress = true;
                        return;
                     }
                  } else {
                     AutoPot.this.strengthPress = false;
                  }

                  if (AutoPot.this.speedKey.isPressed()) {
                     if (!AutoPot.this.speedPress && AutoPot.this.checkThrow(StatusEffects.SPEED.value())) {
                        AutoPot.this.throwPotion(StatusEffects.SPEED.value());
                        AutoPot.this.speedPress = true;
                     }
                  } else {
                     AutoPot.this.speedPress = false;
                  }
               } else {
                  AutoPot.this.speedPress = false;
                  AutoPot.this.turtlePress = false;
                  AutoPot.this.strengthPress = false;
               }
            }
         }
      }
   }
}
