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

import dev.crucifixbeta.CrucifixBeta;
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.EntityUtil;
import dev.crucifixbeta.api.utils.player.InventoryUtil;
import dev.crucifixbeta.core.Manager;
import dev.crucifixbeta.mod.gui.windows.WindowsScreen;
import dev.crucifixbeta.mod.gui.windows.impl.ItemSelectWindow;
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 dev.crucifixbeta.mod.modules.settings.impl.StringSetting;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.BedBlock;
import net.minecraft.block.Blocks;
import net.minecraft.block.LadderBlock;
import net.minecraft.block.PistonBlock;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.PotionContentsComponent;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.screen.slot.SlotActionType;
import org.apache.commons.io.IOUtils;

@Environment(EnvType.CLIENT)
public class Sorter extends Module {
   public static Sorter INSTANCE;
   final int[] stealCountList = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   private final SliderSetting tasksPerTicks = this.add(new SliderSetting("TasksPerTick", 2, 1, 20));
   private final SliderSetting delay = this.add(new SliderSetting("Delay", 0.1, 0.0, 5.0, 0.01).setSuffix("s"));
   private final BooleanSetting stack = this.add(new BooleanSetting("Stack", true));
   private final EnumSetting<Sorter.Mode> trashMode = this.add(new EnumSetting<>("TrashMode", Sorter.Mode.Whitelist));
   private final BooleanSetting edit = this.add(new BooleanSetting("EditTrash", false).injectTask(this::openGui));
   private final BooleanSetting sort = this.add(new BooleanSetting("Sort", true));
   private final BooleanSetting kit = this.add(new BooleanSetting("Kit", false).injectTask(this::onEnable));
   private final StringSetting kitName = this.add(new StringSetting("KitName", "kit1"));
   private final BooleanSetting drop = this.add(new BooleanSetting("Drop", true).setParent());
   private final BooleanSetting trash = this.add(new BooleanSetting("Trash", true, this.drop::isOpen));
   private final BooleanSetting rename = this.add(new BooleanSetting("Rename", true, this.drop::isOpen));
   private final BooleanSetting kitExceed = this.add(new BooleanSetting("KitExceed", true, this.drop::isOpen));
   private final BooleanSetting exceed = this.add(new BooleanSetting("Exceed", true, this.drop::isOpen));
   private final SliderSetting crystal = this.add(new SliderSetting("Crystal", 4, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting exp = this.add(new SliderSetting("Exp", 4, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting totem = this.add(new SliderSetting("Totem", 6, 0, 36, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting eGapple = this.add(new SliderSetting("EGapple", 2, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting gapple = this.add(new SliderSetting("Gapple", 2, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting obsidian = this.add(new SliderSetting("Obsidian", 1, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting web = this.add(new SliderSetting("Web", 1, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting glowstone = this.add(new SliderSetting("Glowstone", 1, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting anchor = this.add(new SliderSetting("Anchor", 1, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting pearl = this.add(new SliderSetting("Pearl", 1, 0, 8, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting piston = this.add(new SliderSetting("Piston", 1, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting redstone = this.add(new SliderSetting("RedStone", 1, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting ladder = this.add(new SliderSetting("Ladder", 2, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting bed = this.add(new SliderSetting("Bed", 4, 0, 12, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting speed = this.add(new SliderSetting("Speed", 1, 0, 8, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting turtle = this.add(new SliderSetting("Resistance", 1, 0, 8, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final SliderSetting strength = this.add(new SliderSetting("Strength", 1, 0, 8, () -> this.drop.isOpen() && this.exceed.isOpen()));
   private final Timer timer = new Timer();
   private final Map<Integer, String> kitMap = new ConcurrentHashMap<>();

   public Sorter() {
      super("Sorter", Module.Category.Player);
      this.setChinese("\u80cc\u5305\u6574\u7406");
      INSTANCE = this;
   }

   @Override
   public void onEnable() {
      if (!nullCheck()) {
         CrucifixBeta.THREAD.execute(() -> {
            this.kitMap.clear();

            try {
               File var1 = Manager.getFile(this.kitName.getValue() + ".kit");
               if (!var1.exists()) {
                  return;
               }

               for (String var4 : IOUtils.readLines(new FileInputStream(var1), StandardCharsets.UTF_8)) {
                  String[] var5 = var4.split(":");
                  if (var5.length != 2) {
                     return;
                  }

                  this.kitMap.put(Integer.valueOf(var5[0]), var5[1]);
               }
            } catch (Exception var6) {
               var6.printStackTrace();
            }
         });
      }
   }

   public static int getItemCount(Item item) {
      int var1 = 0;

      for (Entry var3 : InventoryUtil.getInventoryAndHotbarSlots().entrySet()) {
         if (((ItemStack)var3.getValue()).getItem() == item) {
            var1++;
         }
      }

      if (mc.player.getOffHandStack().getItem() == item) {
         var1++;
      }

      return var1;
   }

   public static int getItemCount(Class<?> clazz) {
      int var1 = 0;

      for (Entry var3 : InventoryUtil.getInventoryAndHotbarSlots().entrySet()) {
         if (((ItemStack)var3.getValue()).getItem() instanceof BlockItem && clazz.isInstance(((BlockItem)((ItemStack)var3.getValue()).getItem()).getBlock())) {
            var1++;
         }
      }

      return var1;
   }

   private void openGui() {
      this.edit.setValueWithoutTask(false);
      if (!nullCheck()) {
         mc.setScreen(new WindowsScreen(new ItemSelectWindow(CrucifixBeta.CLEANER)));
      }
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if (this.timer.passedS(this.delay.getValue())) {
         if (EntityUtil.inInventory()) {
            if (this.exceed.getValue()) {
               this.updateItem();
            }

            for (int var2 = 0; (double)var2 < this.tasksPerTicks.getValue(); var2++) {
               this.tweak();
            }
         }
      }
   }

   private void tweak() {
      if (this.drop.getValue()) {
         for (int var1 = 35; var1 >= 0; var1--) {
            ItemStack var2 = mc.player.getInventory().getStack(var1);
            if (!var2.isEmpty() && this.shouldDrop(var2)) {
               this.timer.reset();
               mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, var1 < 9 ? var1 + 36 : var1, 1, SlotActionType.THROW, mc.player);
               return;
            }
         }
      }

      if (this.stack.getValue()) {
         for (int var9 = 35; var9 >= 9; var9--) {
            ItemStack var14 = mc.player.getInventory().getStack(var9);
            if (!var14.isEmpty() && var14.isStackable() && var14.getCount() != var14.getMaxCount()) {
               for (int var3 = 0; var3 < 36; var3++) {
                  ItemStack var4;
                  if (var9 != var3 && (var4 = mc.player.getInventory().getStack(var3)).getCount() != var4.getMaxCount() && canMerge(var14, var4)) {
                     mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, var9, 0, SlotActionType.PICKUP, mc.player);
                     mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, var3 < 9 ? var3 + 36 : var3, 0, SlotActionType.PICKUP, mc.player);
                     mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, var9, 0, SlotActionType.PICKUP, mc.player);
                     this.timer.reset();
                     return;
                  }
               }
            }
         }
      }

      if (this.drop.getValue()) {
         for (int var10 = 35; var10 >= 0; var10--) {
            ItemStack var15 = mc.player.getInventory().getStack(var10);
            if (!var15.isEmpty() && this.exceed.getValue() && this.exceed(var15, false)) {
               this.timer.reset();
               mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, var10 < 9 ? var10 + 36 : var10, 1, SlotActionType.THROW, mc.player);
               return;
            }
         }
      }

      if (this.sort.getValue()) {
         if (this.kit.getValue()) {
            for (int var11 = 0; var11 < 36; var11++) {
               if (this.kitMap.containsKey(var11)) {
                  String var16 = this.kitMap.get(var11);
                  String var19 = mc.player.getInventory().getStack(var11).getItem().getTranslationKey();
                  if (!var19.equals(var16)) {
                     for (int var5 = 0; var5 < 36; var5++) {
                        String var6 = this.kitMap.get(var5);
                        ItemStack var7 = mc.player.getInventory().getStack(var5);
                        String var8;
                        if (!var7.isEmpty() && !(var8 = var7.getItem().getTranslationKey()).equals(var6) && var8.equals(var16)) {
                           mc.interactionManager
                              .clickSlot(mc.player.playerScreenHandler.syncId, var11 < 9 ? var11 + 36 : var11, 0, SlotActionType.PICKUP, mc.player);
                           mc.interactionManager
                              .clickSlot(mc.player.playerScreenHandler.syncId, var5 < 9 ? var5 + 36 : var5, 0, SlotActionType.PICKUP, mc.player);
                           mc.interactionManager
                              .clickSlot(mc.player.playerScreenHandler.syncId, var11 < 9 ? var11 + 36 : var11, 0, SlotActionType.PICKUP, mc.player);
                           this.timer.reset();
                           return;
                        }
                     }
                  }
               }
            }
         } else {
            for (int var12 = 9; var12 < 36; var12++) {
               int var20 = Item.getRawId(mc.player.getInventory().getStack(var12).getItem());
               if (mc.player.getInventory().getStack(var12).isEmpty()) {
                  var20 = 114514;
               }

               int var17;
               if ((var17 = this.getMinId(var12, var20)) < var20) {
                  for (int var22 = 35; var22 > var12; var22--) {
                     ItemStack var24 = mc.player.getInventory().getStack(var22);
                     if (!var24.isEmpty() && Item.getRawId(var24.getItem()) == var17) {
                        mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, var12, 0, SlotActionType.PICKUP, mc.player);
                        mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, var22, 0, SlotActionType.PICKUP, mc.player);
                        mc.interactionManager.clickSlot(mc.player.playerScreenHandler.syncId, var12, 0, SlotActionType.PICKUP, mc.player);
                        this.timer.reset();
                        return;
                     }
                  }
               }
            }
         }
      }

      if (this.drop.getValue() && this.kitExceed.getValue()) {
         for (int var13 = 35; var13 >= 0; var13--) {
            if (this.kitMap.containsKey(var13)) {
               ItemStack var23 = mc.player.getInventory().getStack(var13);
               BlockItem var18;
               Item var21;
               if ((!this.exceed.getValue() || this.exceed(var23, true))
                  && !var23.isEmpty()
                  && !(var23.getItem() instanceof ArmorItem)
                  && (!((var21 = var23.getItem()) instanceof BlockItem) || !((var18 = (BlockItem)var21).getBlock() instanceof ShulkerBoxBlock))
                  && !var23.getItem().getTranslationKey().equals(this.kitMap.get(var13))) {
                  this.timer.reset();
                  mc.interactionManager.clickSlot(mc.player.currentScreenHandler.syncId, var13 < 9 ? var13 + 36 : var13, 1, SlotActionType.THROW, mc.player);
                  return;
               }
            }
         }
      }
   }

   private boolean shouldDrop(ItemStack stack) {
      Item var2 = stack.getItem();
      BlockItem var3;
      boolean var4;
      if (!this.trash.getValue()
         || var2 instanceof BlockItem && (var3 = (BlockItem)var2).getBlock() instanceof ShulkerBoxBlock
         || ((var4 = CrucifixBeta.CLEANER.inList(var2.getTranslationKey())) || !this.trashMode.is(Sorter.Mode.Whitelist))
            && (!var4 || !this.trashMode.is(Sorter.Mode.Blacklist))) {
         return !this.rename.getValue() ? false : stack.isStackable() && !stack.getName().getString().equals(var2.getName().getString());
      } else {
         return true;
      }
   }

   private boolean exceed(ItemStack i, boolean dropOther) {
      if (i.getItem().equals(Items.END_CRYSTAL)) {
         if ((double)this.stealCountList[0] > this.crystal.getValue()) {
            this.stealCountList[0]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Items.EXPERIENCE_BOTTLE)) {
         if ((double)this.stealCountList[1] > this.exp.getValue()) {
            this.stealCountList[1]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Items.TOTEM_OF_UNDYING)) {
         if ((double)this.stealCountList[2] > this.totem.getValue()) {
            this.stealCountList[2]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Items.ENCHANTED_GOLDEN_APPLE)) {
         if ((double)this.stealCountList[3] > this.eGapple.getValue()) {
            this.stealCountList[3]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Blocks.OBSIDIAN.asItem())) {
         if ((double)this.stealCountList[4] > this.obsidian.getValue()) {
            this.stealCountList[4]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Blocks.COBWEB.asItem())) {
         if ((double)this.stealCountList[5] > this.web.getValue()) {
            this.stealCountList[5]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Blocks.GLOWSTONE.asItem())) {
         if ((double)this.stealCountList[6] > this.glowstone.getValue()) {
            this.stealCountList[6]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Blocks.RESPAWN_ANCHOR.asItem())) {
         if ((double)this.stealCountList[7] > this.anchor.getValue()) {
            this.stealCountList[7]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Items.ENDER_PEARL)) {
         if ((double)this.stealCountList[8] > this.pearl.getValue()) {
            this.stealCountList[8]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem() instanceof BlockItem && ((BlockItem)i.getItem()).getBlock() instanceof PistonBlock) {
         if ((double)this.stealCountList[9] > this.piston.getValue()) {
            this.stealCountList[9]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem().equals(Blocks.REDSTONE_BLOCK.asItem())) {
         if ((double)this.stealCountList[10] > this.redstone.getValue()) {
            this.stealCountList[10]--;
            return true;
         } else {
            return false;
         }
      } else if (i.getItem() instanceof BlockItem && ((BlockItem)i.getItem()).getBlock() instanceof BedBlock) {
         if ((double)this.stealCountList[11] > this.bed.getValue()) {
            this.stealCountList[11]--;
            return true;
         } else {
            return false;
         }
      } else {
         if (Item.getRawId(i.getItem()) == Item.getRawId(Items.SPLASH_POTION)) {
            PotionContentsComponent var3 = i.getOrDefault(DataComponentTypes.POTION_CONTENTS, PotionContentsComponent.DEFAULT);

            for (StatusEffectInstance var5 : var3.getEffects()) {
               if (var5.getEffectType().value() == StatusEffects.SPEED.value()) {
                  if ((double)this.stealCountList[12] > this.speed.getValue()) {
                     this.stealCountList[12]--;
                     return true;
                  }

                  return false;
               }

               if (var5.getEffectType().value() == StatusEffects.RESISTANCE.value()) {
                  if ((double)this.stealCountList[13] > this.turtle.getValue()) {
                     this.stealCountList[13]--;
                     return true;
                  }

                  return false;
               }

               if (var5.getEffectType().value() == StatusEffects.STRENGTH.value()) {
                  if ((double)this.stealCountList[16] > this.strength.getValue()) {
                     this.stealCountList[16]--;
                     return true;
                  }

                  return false;
               }
            }
         }

         if (i.getItem().equals(Items.GOLDEN_APPLE) && (double)this.stealCountList[14] > this.gapple.getValue()) {
            this.stealCountList[14]--;
            return true;
         } else if (i.getItem() instanceof BlockItem
            && ((BlockItem)i.getItem()).getBlock() instanceof LadderBlock
            && (double)this.stealCountList[15] > this.ladder.getValue()) {
            this.stealCountList[15]--;
            return true;
         } else {
            return dropOther;
         }
      }
   }

   private void updateItem() {
      this.stealCountList[0] = getItemCount(Items.END_CRYSTAL);
      this.stealCountList[1] = getItemCount(Items.EXPERIENCE_BOTTLE);
      this.stealCountList[2] = getItemCount(Items.TOTEM_OF_UNDYING);
      this.stealCountList[3] = getItemCount(Items.ENCHANTED_GOLDEN_APPLE);
      this.stealCountList[4] = getItemCount(Items.OBSIDIAN);
      this.stealCountList[5] = getItemCount(Items.COBWEB);
      this.stealCountList[6] = getItemCount(Items.GLOWSTONE);
      this.stealCountList[7] = getItemCount(Items.RESPAWN_ANCHOR);
      this.stealCountList[8] = getItemCount(Items.ENDER_PEARL);
      this.stealCountList[9] = getItemCount(Items.PISTON) - getItemCount(Items.STICKY_PISTON);
      this.stealCountList[10] = getItemCount(Items.REDSTONE_BLOCK);
      this.stealCountList[11] = getItemCount(BedBlock.class);
      this.stealCountList[12] = InventoryUtil.getPotionCount(StatusEffects.SPEED.value());
      this.stealCountList[13] = InventoryUtil.getPotionCount(StatusEffects.RESISTANCE.value());
      this.stealCountList[14] = getItemCount(Items.GOLDEN_APPLE);
      this.stealCountList[15] = getItemCount(LadderBlock.class);
      this.stealCountList[16] = InventoryUtil.getPotionCount(StatusEffects.STRENGTH.value());
   }

   private int getMinId(int slot, int currentId) {
      int var3 = currentId;

      for (int var4 = slot + 1; var4 < 36; var4++) {
         ItemStack var5 = mc.player.getInventory().getStack(var4);
         int var6;
         if (!var5.isEmpty() && (var6 = Item.getRawId(var5.getItem())) < var3) {
            var3 = var6;
         }
      }

      return var3;
   }

   public static boolean canMerge(ItemStack source, ItemStack stack) {
      return ItemStack.areItemsAndComponentsEqual(source, stack);
   }
@Environment(EnvType.CLIENT)
   private static enum Mode {
      Whitelist,
      Blacklist;

}
}
