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

import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.utils.math.Timer;
import dev.crucifixbeta.api.utils.player.InventoryUtil;
import dev.crucifixbeta.api.utils.world.BlockUtil;
import dev.crucifixbeta.mod.modules.Module;
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.block.BlockState;
import net.minecraft.block.FenceGateBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;

@Environment(EnvType.CLIENT)
public class FenceGateAura extends Module {
   public static FenceGateAura INSTANCE;
   private final SliderSetting delay = this.add(new SliderSetting("Delay", 100, 0, 500).setSuffix("ms"));
   private final SliderSetting range = this.add(new SliderSetting("Range", 5.0, 0.0, 8.0).setSuffix("m"));
   private final SliderSetting placeRange = this.add(new SliderSetting("PlaceRange", 4.5, 0.0, 6.0).setSuffix("m"));
   private final SliderSetting predictTicks = this.add(new SliderSetting("PredictTicks", 2.0, 0.0, 50.0, 1.0));
   private final BooleanSetting rotate = this.add(new BooleanSetting("Rotate", true));
   private final BooleanSetting silent = this.add(new BooleanSetting("Silent", false));
   private final BooleanSetting inventory = this.add(new BooleanSetting("InventorySwap", true));
   private final BooleanSetting ghostHand = this.add(new BooleanSetting("GhostHand", true));
   private final BooleanSetting autoDisable = this.add(new BooleanSetting("AutoDisable", false));
   private final Timer timer = new Timer();

   public FenceGateAura() {
      super("FenceGateAura", Module.Category.Combat);
      this.setChinese("\u6805\u680f\u95e8\u5149\u73af");
      INSTANCE = this;
   }

   @Override
   public void onEnable() {
      this.timer.reset();
   }

   @EventListener
   public void onUpdate(UpdateEvent e) {
      if (!nullCheck() && this.timer.passedMs(this.delay.getValue())) {
         PlayerEntity var2 = this.findTarget();
         if (var2 == null) {
            if (this.autoDisable.getValue()) {
               this.disable();
            }
         } else {
            int var3 = this.findFenceGateSlot();
            if (var3 != -1) {
               this.placeAround(var2, var3);
               this.timer.reset();
            }
         }
      }
   }

   private PlayerEntity findTarget() {
      PlayerEntity var1 = null;
      double var2 = this.range.getValue();

      for (PlayerEntity var5 : mc.world.getPlayers()) {
         if (var5 != mc.player && !var5.isDead() && var5.isAlive()) {
            double var6 = (double)mc.player.distanceTo(var5);
            if (var6 < var2) {
               var2 = var6;
               var1 = var5;
            }
         }
      }

      return var1;
   }

   private int findFenceGateSlot() {
      for (int var1 = 0; var1 < 45; var1++) {
         ItemStack var2 = mc.player.getInventory().getStack(var1);
         if (var2.getItem() instanceof BlockItem var4 && var4.getBlock() instanceof FenceGateBlock) {
            return var1;
         }
      }

      return -1;
   }

   private void placeAround(PlayerEntity target, int slot) {
      BlockPos var3 = target.getBlockPos();
      int var4 = 0;

      for (int var5 = -1; var5 <= 1; var5++) {
         for (int var6 = -1; var6 <= 1; var6++) {
            if (var5 != 0 || var6 != 0) {
               BlockPos var7 = var3.add(var5, 0, var6);
               if (!(mc.player.getEyePos().distanceTo(var7.toCenterPos()) > this.placeRange.getValue())) {
                  if (!mc.world.isAir(var7)) {
                     this.toggleGate(var7);
                  } else if (mc.world.getBlockState(var7.down()).isSolidBlock(mc.world, var7.down())) {
                     this.placeGate(var7, slot);
                     if (++var4 >= 8) {
                        break;
                     }
                  }
               }
            }
         }

         if (var4 >= 8) {
            break;
         }
      }
   }

   private void placeGate(BlockPos pos, int slot) {
      int var3 = mc.player.getInventory().selectedSlot;
      if (this.ghostHand.getValue()) {
         InventoryUtil.inventorySwap(slot, var3);
      } else {
         InventoryUtil.switchToSlot(slot);
      }

      BlockUtil.placeBlock(pos, this.rotate.getValue());
      this.toggleGate(pos);
      if (this.ghostHand.getValue()) {
         InventoryUtil.inventorySwap(slot, var3);
      } else {
         InventoryUtil.switchToSlot(var3);
      }
   }

   private void toggleGate(BlockPos pos) {
      BlockState var2 = mc.world.getBlockState(pos);
      if (var2.getBlock() instanceof FenceGateBlock) {
         if (!(mc.player.getEyePos().distanceTo(pos.toCenterPos()) > this.placeRange.getValue())) {
            Direction var3 = BlockUtil.getClickSide(pos);
            if (var3 != null) {
               BlockUtil.clickBlock(pos, var3, this.rotate.getValue());
            }
         }
      }
   }
}
