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

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.events.impl.UpdateRotateEvent;
import dev.crucifixbeta.api.utils.math.Timer;
import dev.crucifixbeta.api.utils.player.EntityUtil;
import dev.crucifixbeta.api.utils.player.InventoryUtil;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.settings.enums.SwingSide;
import dev.crucifixbeta.mod.modules.settings.impl.BooleanSetting;
import dev.crucifixbeta.mod.modules.settings.impl.EnumSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.component.type.ItemEnchantmentsComponent;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
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 AutoXP extends Module {
   public static AutoXP INSTANCE;
   public final BooleanSetting rotation = this.add(new BooleanSetting("Rotation", true).setParent());
   private final BooleanSetting instant = this.add(new BooleanSetting("Instant", false, this.rotation::isOpen));
   public final BooleanSetting onlyBroken = this.add(new BooleanSetting("OnlyBroken", true));
   private final SliderSetting delay = this.add(new SliderSetting("Delay", 3, 0, 5));
   private final BooleanSetting inventory = this.add(new BooleanSetting("InventorySwap", true));
   public final EnumSetting<SwingSide> interactSwing = this.add(new EnumSetting<>("InteractSwing", SwingSide.All));
   private final BooleanSetting usingPause = this.add(new BooleanSetting("UsingPause", true));
   private final BooleanSetting onlyGround = this.add(new BooleanSetting("OnlyGround", true));
   public final BooleanSetting autoDisable = this.add(new BooleanSetting("AutoDisable", true));
   private final Timer delayTimer = new Timer();
   private boolean lookDown;
   private boolean throwing;
   private int exp;

   public AutoXP() {
      super("AutoXP", Module.Category.Combat);
      this.setChinese("\u81ea\u52a8\u7ecf\u9a8c\u74f6");
      this.rotation.setChinese("\u65cb\u8f6c");
      this.instant.setChinese("\u77ac\u95f4\u65cb\u8f6c");
      this.onlyBroken.setChinese("\u4ec5\u635f\u574f\u88c5\u5907");
      this.delay.setChinese("\u5ef6\u8fdf");
      this.inventory.setChinese("\u80cc\u5305\u4ea4\u6362");
      this.interactSwing.setChinese("\u4ea4\u4e92\u6325\u624b");
      this.usingPause.setChinese("\u4f7f\u7528\u7269\u54c1\u6682\u505c");
      this.onlyGround.setChinese("\u4ec5\u5730\u9762");
      this.autoDisable.setChinese("\u81ea\u52a8\u5173\u95ed");
      INSTANCE = this;
   }

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

   @Override
   public void onEnable() {
      this.lookDown = !this.rotation.getValue() || this.instant.getValue();
      if (nullCheck()) {
         this.disable();
      } else {
         this.exp = InventoryUtil.getItemCount(Items.EXPERIENCE_BOTTLE);
      }
   }

   @Override
   public String getInfo() {
      return String.valueOf(this.exp);
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      this.throwing = this.checkThrow();
      if (!this.inventory.getValue() || EntityUtil.inInventory()) {
         if (this.lookDown
            && this.isThrow()
            && this.delayTimer.passed((long)this.delay.getValueInt() * 20L)
            && (!this.onlyGround.getValue() || mc.player.isOnGround())) {
            this.exp = InventoryUtil.getItemCount(Items.EXPERIENCE_BOTTLE) - 1;
            if (this.rotation.getValue() && this.instant.getValue()) {
               CrucifixBeta.ROTATION.snapAt(CrucifixBeta.ROTATION.rotationYaw, 88.0F);
            }

            this.throwExp();
            if (this.rotation.getValue() && this.instant.getValue()) {
               CrucifixBeta.ROTATION.snapBack();
            }
         }

         if (this.autoDisable.getValue() && !this.isThrow()) {
            this.disable();
         }
      }
   }

   public void throwExp() {
      int var1 = mc.player.getInventory().selectedSlot;
      int var2;
      if (this.inventory.getValue() && (var2 = InventoryUtil.findItemInventorySlotFromZero(Items.EXPERIENCE_BOTTLE)) != -1) {
         InventoryUtil.inventorySwap(var2, mc.player.getInventory().selectedSlot);
         sendSequencedPacket(
            id -> new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, id, CrucifixBeta.ROTATION.getLastYaw(), CrucifixBeta.ROTATION.getLastPitch())
         );
         EntityUtil.swingHand(Hand.MAIN_HAND, this.interactSwing.getValue());
         InventoryUtil.inventorySwap(var2, mc.player.getInventory().selectedSlot);
         EntityUtil.syncInventory();
         this.delayTimer.reset();
      } else if ((var2 = InventoryUtil.findItem(Items.EXPERIENCE_BOTTLE)) != -1) {
         InventoryUtil.switchToSlot(var2);
         sendSequencedPacket(
            id -> new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, id, CrucifixBeta.ROTATION.getLastYaw(), CrucifixBeta.ROTATION.getLastPitch())
         );
         EntityUtil.swingHand(Hand.MAIN_HAND, this.interactSwing.getValue());
         InventoryUtil.switchToSlot(var1);
         this.delayTimer.reset();
      }
   }

   @EventListener(
      priority = -200
   )
   public void onRotate(UpdateRotateEvent event) {
      if (this.rotation.getValue() && !this.instant.getValue() && this.isThrow()) {
         event.setPitch(88.0F);
         this.lookDown = true;
      }
   }

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

   public boolean checkThrow() {
      if (this.isOff() || mc.currentScreen != null) {
         return false;
      } else if (this.usingPause.getValue() && this.shouldPauseForUsingItem()) {
         return false;
      } else if (InventoryUtil.findItem(Items.EXPERIENCE_BOTTLE) != -1
         || this.inventory.getValue() && InventoryUtil.findItemInventorySlotFromZero(Items.EXPERIENCE_BOTTLE) != -1) {
         if (!this.onlyBroken.getValue()) {
            return true;
         } else {
            for (ItemStack var2 : mc.player.getInventory().armor) {
               if (!var2.isEmpty() && EntityUtil.getDamagePercent(var2) < 100) {
                  ItemEnchantmentsComponent var3 = EnchantmentHelper.getEnchantments(var2);
                  return var3.getEnchantments()
                     .contains(mc.world.getRegistryManager().get(Enchantments.MENDING.getRegistryRef()).getEntry(Enchantments.MENDING).get());
               }
            }

            return false;
         }
      } else {
         return false;
      }
   }
}
