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

import asm.accessors.IPlayerInteractEntityC2SPacket;
import asm.accessors.IPlayerMoveC2SPacket;
import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.PacketEvent;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.utils.player.EntityUtil;
import dev.crucifixbeta.api.utils.player.MovementUtil;
import dev.crucifixbeta.api.utils.world.BlockUtil;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.impl.exploit.Blink;
import dev.crucifixbeta.mod.modules.impl.exploit.BowBomb;
import dev.crucifixbeta.mod.modules.impl.exploit.Phase;
import dev.crucifixbeta.mod.modules.impl.player.AutoPearl;
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.entity.Entity;
import net.minecraft.entity.decoration.EndCrystalEntity;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket.Handler;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket.InteractType;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.Full;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.PositionAndOnGround;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;

@Environment(EnvType.CLIENT)
public class Criticals extends Module {
   public static Criticals INSTANCE;
   public final EnumSetting<Criticals.Mode> mode = this.add(new EnumSetting<>("Mode", Criticals.Mode.GrimV3));
   public final BooleanSetting onlyGround = this.add(new BooleanSetting("OnlyGround", true, () -> !this.mode.is(Criticals.Mode.Ground)));
   private final BooleanSetting setOnGround = this.add(new BooleanSetting("SetNoGround", false, () -> this.mode.is(Criticals.Mode.Ground)));
   private final BooleanSetting blockCheck = this.add(new BooleanSetting("BlockCheck", true, () -> this.mode.is(Criticals.Mode.Ground)));
   private final BooleanSetting autoJump = this.add(
      new BooleanSetting("AutoJump", true, () -> this.mode.is(Criticals.Mode.Ground)).setParent()
   );
   private final BooleanSetting mini = this.add(
      new BooleanSetting("Mini", true, () -> this.mode.is(Criticals.Mode.Ground) && this.autoJump.isOpen())
   );
   private final SliderSetting y = this.add(
      new SliderSetting("MotionY", 0.05, 0.0, 1.0, 0.001, () -> this.mode.is(Criticals.Mode.Ground) && this.autoJump.isOpen())
   );
   private final BooleanSetting crawlingDisable = this.add(new BooleanSetting("CrawlingDisable", true, () -> this.mode.is(Criticals.Mode.Ground)));
   private final BooleanSetting flight = this.add(new BooleanSetting("Flight", false, () -> this.mode.is(Criticals.Mode.Ground)));
   private final BooleanSetting pauseOnMove = this.add(new BooleanSetting("PauseOnMove", true));
   private final BooleanSetting moveDisable = this.add(new BooleanSetting("MoveDisable", false));
   private final BooleanSetting onlyWhenStuck = this.add(new BooleanSetting("OnlyInBlock", true));
   boolean requireJump = false;
   private boolean wasMoving = false;

   public Criticals() {
      super("Criticals", Module.Category.Combat);
      this.setChinese("\u5200\u5200\u66b4\u51fb");
      INSTANCE = this;
   }

   @Override
   public String getInfo() {
      return this.mode.is(Criticals.Mode._3c3u) ? "3c3u" : this.mode.getValue().name();
   }

   private boolean isStuck() {
      if (mc.player != null && mc.world != null) {
         Box var1 = mc.player.getBoundingBox();
         int var2 = (int)Math.floor(var1.minX);
         int var3 = (int)Math.floor(var1.maxX);
         int var4 = (int)Math.floor(var1.minY);
         int var5 = (int)Math.floor(var1.maxY);
         int var6 = (int)Math.floor(var1.minZ);
         int var7 = (int)Math.floor(var1.maxZ);

         for (int var8 = var2; var8 <= var3; var8++) {
            for (int var9 = var4; var9 <= var5; var9++) {
               for (int var10 = var6; var10 <= var7; var10++) {
                  BlockPos var11 = new BlockPos(var8, var9, var10);
                  if (mc.world.getBlockState(var11).isSolidBlock(mc.world, var11)) {
                     return true;
                  }
               }
            }
         }

         return false;
      } else {
         return false;
      }
   }

   @EventListener
   public void onPacketSend(PacketEvent.Send event) {
      if (!event.isCancelled()) {
         if (!nullCheck()) {
            if (!Blink.INSTANCE.isOn() || !Blink.INSTANCE.pauseModule.getValue()) {
               if (!this.disableOnMove()) {
                  if (this.mode.is(Criticals.Mode._3c3u)) {
                     Packet var5 = event.getPacket();
                     PlayerInteractEntityC2SPacket var6;
                     Entity var7;
                     if (var5 instanceof PlayerInteractEntityC2SPacket
                        && getInteractType(var6 = (PlayerInteractEntityC2SPacket)var5) == InteractType.ATTACK
                        && !((var7 = getEntity(var6)) instanceof EndCrystalEntity)
                        && (!this.onlyGround.getValue() || mc.player.isOnGround() || mc.player.getAbilities().flying)
                        && !mc.player.isInLava()
                        && !mc.player.isSubmergedInWater()
                        && var7 != null) {
                        if (!MovementUtil.isMoving() && MovementUtil.isStatic()) {
                           this.do3c3uCrit();
                        }
                     }
                  } else if (!this.onlyWhenStuck.getValue() || this.isStuck()) {
                     if (this.mode.is(Criticals.Mode.Ground)) {
                        if (!BowBomb.send) {
                           if (!AutoPearl.throwing && !Phase.INSTANCE.isOn()) {
                              if (this.setOnGround.getValue()) {
                                 if (!this.pauseOnMove.getValue() || !MovementUtil.isMoving()) {
                                    if (event.getPacket() instanceof PlayerMoveC2SPacket) {
                                       ((IPlayerMoveC2SPacket)event.getPacket()).setOnGround(false);
                                    }
                                 }
                              }
                           }
                        }
                     } else {
                        Packet var2 = event.getPacket();
                        PlayerInteractEntityC2SPacket var3;
                        Entity var4;
                        if (var2 instanceof PlayerInteractEntityC2SPacket
                           && getInteractType(var3 = (PlayerInteractEntityC2SPacket)var2) == InteractType.ATTACK
                           && !((var4 = getEntity(var3)) instanceof EndCrystalEntity)
                           && (!this.onlyGround.getValue() || mc.player.isOnGround() || mc.player.getAbilities().flying)
                           && !mc.player.isInLava()
                           && !mc.player.isTouchingWater()
                           && var4 != null) {
                           if (this.pauseOnMove.getValue() && MovementUtil.isMoving()) {
                              return;
                           }

                           this.doCrit(var4);
                        }
                     }
                  }
               }
            }
         }
      }
   }

   @Override
   public void onLogout() {
   }

   @Override
   public void onEnable() {
      if (!Blink.INSTANCE.isOn() || !Blink.INSTANCE.pauseModule.getValue()) {
         this.requireJump = true;
         this.wasMoving = false;
         if (this.mode.is(Criticals.Mode.Ground)) {
            if (nullCheck()) {
               return;
            }

            if (this.crawlingDisable.getValue() && mc.player.isCrawling()) {
               this.disable();
               return;
            }

            if (this.onlyWhenStuck.getValue() && !this.isStuck()) {
               return;
            }

            if (mc.player.isOnGround()
               && this.autoJump.getValue()
               && (!this.blockCheck.getValue() || BlockUtil.canCollide(mc.player, new Box(EntityUtil.getPlayerPos(true).up(2))))
               && (!this.pauseOnMove.getValue() || !MovementUtil.isMoving())) {
               this.jump();
            }
         }
      }
   }

   public void jump() {
      if (this.mini.getValue()) {
         MovementUtil.setMotionY(this.y.getValue());
      } else {
         mc.player.jump();
      }
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if (!Blink.INSTANCE.isOn() || !Blink.INSTANCE.pauseModule.getValue()) {
         if (!this.disableOnMove()) {
            if (this.mode.is(Criticals.Mode.Ground)) {
               if (this.onlyWhenStuck.getValue() && !this.isStuck()) {
                  this.wasMoving = MovementUtil.isMoving();
                  return;
               }

               boolean var2 = MovementUtil.isMoving();
               if (this.pauseOnMove.getValue()
                  && this.wasMoving
                  && !var2
                  && mc.player.isOnGround()
                  && this.autoJump.getValue()
                  && (!this.blockCheck.getValue() || BlockUtil.canCollide(mc.player, new Box(EntityUtil.getPlayerPos(true).up(2))))) {
                  this.jump();
                  this.requireJump = false;
               }

               this.wasMoving = var2;
               if (this.crawlingDisable.getValue() && mc.player.isCrawling()) {
                  this.disable();
               } else if (this.flight.getValue() && mc.player.fallDistance > 0.0F) {
                  MovementUtil.setMotionY(0.0);
                  MovementUtil.setMotionX(0.0);
                  MovementUtil.setMotionZ(0.0);
                  this.requireJump = false;
               } else if (this.blockCheck.getValue() && !BlockUtil.canCollide(mc.player, new Box(EntityUtil.getPlayerPos(true).up(2)))) {
                  this.requireJump = true;
               } else if (mc.player.isOnGround()
                  && this.autoJump.getValue()
                  && (this.flight.getValue() || this.requireJump)
                  && (!this.pauseOnMove.getValue() || !var2)) {
                  this.jump();
                  this.requireJump = false;
               }
            }
         }
      }
   }

   private boolean disableOnMove() {
      if (this.moveDisable.getValue() && !nullCheck() && MovementUtil.isMoving()) {
         this.disable();
         return true;
      } else {
         return false;
      }
   }

   public void doCrit(Entity entity) {
      switch ((Criticals.Mode)this.mode.getValue()) {
         case UpdatedNCP:
            mc.player.addCritParticles(entity);
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 2.71875E-7, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY(), mc.player.getZ(), false));
            break;
         case Strict:
            mc.player.addCritParticles(entity);
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.062600301692775, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.07260029960661, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY(), mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY(), mc.player.getZ(), false));
            break;
         case NCP:
            mc.player.addCritParticles(entity);
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.0625, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY(), mc.player.getZ(), false));
            break;
         case GrimV3:
            mc.player.addCritParticles(entity);
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 1.058293536E-5, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 9.16580235E-6, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 1.0371854E-7, mc.player.getZ(), false));
            break;
         case Hypixel2K22:
            mc.player.addCritParticles(entity);
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.0045, mc.player.getZ(), true));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 1.52121E-4, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.3, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.025, mc.player.getZ(), false));
            break;
         case Packet:
            mc.player.addCritParticles(entity);
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 5.0E-4, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 1.0E-4, mc.player.getZ(), false));
         case Ground:
         default:
            break;
         case BBTT:
            if (MovementUtil.isMoving() || !MovementUtil.isStatic()) {
               return;
            }

            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY(), mc.player.getZ(), true));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.0625, mc.player.getZ(), false));
            mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), mc.player.getY() + 0.045, mc.player.getZ(), false));
      }
   }

   private void do3c3uCrit() {
      float var1 = CrucifixBeta.ROTATION != null ? CrucifixBeta.ROTATION.rotationYaw : mc.player.getYaw();
      float var2 = CrucifixBeta.ROTATION != null ? CrucifixBeta.ROTATION.rotationPitch : mc.player.getPitch();
      mc.getNetworkHandler().sendPacket(new Full(mc.player.getX(), mc.player.getY(), mc.player.getZ(), var1, var2, true));
      mc.getNetworkHandler().sendPacket(new Full(mc.player.getX(), mc.player.getY() + 0.0625, mc.player.getZ(), var1, var2, false));
      mc.getNetworkHandler().sendPacket(new Full(mc.player.getX(), mc.player.getY() + 0.045, mc.player.getZ(), var1, var2, false));
   }

   public static Entity getEntity(PlayerInteractEntityC2SPacket packet) {
      return mc.world == null ? null : mc.world.getEntityById(((IPlayerInteractEntityC2SPacket)packet).getEntityId());
   }

   public static InteractType getInteractType(PlayerInteractEntityC2SPacket packet) {
      final InteractType[] var1 = new InteractType[1];
      packet.handle(new Handler() {
         @Override
         public void interact(Hand hand) {
            var1[0] = InteractType.INTERACT;
         }

         @Override
         public void interactAt(Hand hand, Vec3d pos) {
            var1[0] = InteractType.INTERACT_AT;
         }

         @Override
         public void attack() {
            var1[0] = InteractType.ATTACK;
         }
      });
      return var1[0];
   }
@Environment(EnvType.CLIENT)
   public static enum Mode {
      UpdatedNCP,
      Strict,
      NCP,
      GrimV3,
      Hypixel2K22,
      Packet,
      Ground,
      BBTT,
      _3c3u;

}
}
