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

import asm.accessors.IContainerComponent;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.api.utils.math.Timer;
import dev.crucifixbeta.api.utils.render.Render2DUtil;
import dev.crucifixbeta.core.impl.PlayerManager;
import dev.crucifixbeta.mod.gui.PeekScreen;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.settings.impl.BooleanSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import java.awt.Color;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Objects;
import java.util.UUID;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.DiffuseLighting;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.ComponentMap;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.util.collection.DefaultedList;
import org.lwjgl.opengl.GL11;
import org.spongepowered.asm.mixin.Unique;

@Environment(EnvType.CLIENT)
public class ShulkerViewer extends Module {
   private static final ItemStack[] ITEMS;
   public static ShulkerViewer INSTANCE;
   private static int offset;
   public final BooleanSetting toolTips = this.add(new BooleanSetting("ToolTips", true));
   public final BooleanSetting icon = this.add(new BooleanSetting("Icon", true));
   private final HashMap<UUID, ShulkerViewer.Shulker> map = new HashMap<>();
   private final BooleanSetting peek = this.add(new BooleanSetting("Peek", false).setParent());
   private final SliderSetting renderTime = this.add(
      new SliderSetting("RenderTime", 10.0, 0.0, 100.0, 0.1, this.peek::isOpen).setSuffix("s")
   );
   private final SliderSetting xOffset = this.add(new SliderSetting("X", 0, 0, 1500, this.peek::isOpen));
   private final SliderSetting yOffset = this.add(new SliderSetting("Y", 120, 0, 1000, this.peek::isOpen));
   private final SliderSetting space = this.add(new SliderSetting("Space", 78.0, 0.0, 200.0, 1.0, this.peek::isOpen));

   public ShulkerViewer() {
      super("ShulkerViewer", Module.Category.Misc);
      this.setChinese("\u6f5c\u5f71\u76d2\u67e5\u770b");
      INSTANCE = this;
   }

   public static void renderShulkerToolTip(DrawContext context, int mouseX, int mouseY, ItemStack stack) {
      getItemsInContainerItem(stack, ITEMS);
      draw(context, mouseX, mouseY);
   }

   @Unique
   private static void draw(DrawContext context, int mouseX, int mouseY) {
      RenderSystem.disableDepthTest();
      GL11.glClear(256);
      MatrixStack var10000 = context.getMatrices();
      mouseX += 8;
      float var10001 = (float)mouseX;
      mouseY -= 82;
      Render2DUtil.drawRect(var10000, var10001, (float)mouseY, 176.0F, 67.0F, new Color(0, 0, 0, 120));
      DiffuseLighting.enableGuiDepthLighting();
      int var3 = 0;
      int var4 = 0;

      for (ItemStack var8 : ITEMS) {
         context.drawItem(var8, mouseX + 8 + var4 * 18, mouseY + 7 + var3 * 18);
         context.drawItemInSlot(mc.textRenderer, var8, mouseX + 8 + var4 * 18, mouseY + 7 + var3 * 18);
         if (++var4 >= 9) {
            var4 = 0;
            var3++;
         }
      }

      DiffuseLighting.disableGuiDepthLighting();
      RenderSystem.enableDepthTest();
   }

   public static boolean hasItems(ItemStack itemStack) {
      IContainerComponent var1 = (IContainerComponent)(Object)itemStack.get(DataComponentTypes.CONTAINER);
      if (var1 != null && !var1.getStacks().isEmpty()) {
         return true;
      } else {
         NbtCompound var2 = itemStack.getOrDefault(DataComponentTypes.BLOCK_ENTITY_DATA, NbtComponent.DEFAULT).getNbt();
         return var2 != null && var2.contains("Items", 9);
      }
   }

   public static void getItemsInContainerItem(ItemStack itemStack, ItemStack[] items) {
      if (itemStack.getItem() == Items.ENDER_CHEST) {
         for (int var8 = 0; var8 < CrucifixBeta.PLAYER.ENDERCHEST_ITEM.size(); var8++) {
            items[var8] = CrucifixBeta.PLAYER.ENDERCHEST_ITEM.get(var8);
         }
      } else {
         Arrays.fill(items, ItemStack.EMPTY);
         ComponentMap var3 = itemStack.getComponents();
         if (!var3.contains(DataComponentTypes.CONTAINER)) {
            NbtComponent var6;
            if (var3.contains(DataComponentTypes.BLOCK_ENTITY_DATA)
               && (var6 = var3.get(DataComponentTypes.BLOCK_ENTITY_DATA)).contains("Items")) {
               NbtList var2 = (NbtList)var6.getNbt().get("Items");

               for (int var4 = 0; var4 < var2.size(); var4++) {
                  byte var5 = var2.getCompound(var4).getByte("Slot");
                  if (var5 >= 0 && var5 < items.length) {
                     items[var5] = ItemStack.fromNbtOrEmpty(mc.player.getRegistryManager(), var2.getCompound(var4));
                  }
               }
            }
         } else {
            IContainerComponent var7 = (IContainerComponent)(Object)var3.get(DataComponentTypes.CONTAINER);
            DefaultedList var9 = var7.getStacks();

            for (int var10 = 0; var10 < var9.size(); var10++) {
               if (var10 >= 0 && var10 < items.length) {
                  items[var10] = (ItemStack)var9.get(var10);
               }
            }
         }
      }
   }

   public static boolean openContainer(ItemStack itemStack, ItemStack[] contents, boolean pause) {
      if (!hasItems(itemStack) && itemStack.getItem() != Items.ENDER_CHEST) {
         return false;
      } else {
         getItemsInContainerItem(itemStack, contents);
         if (pause) {
            PlayerManager.screenToOpen = new PeekScreen(itemStack, contents);
         } else {
            mc.setScreen(new PeekScreen(itemStack, contents));
         }

         return true;
      }
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if (this.peek.getValue()) {
         for (AbstractClientPlayerEntity var3 : CrucifixBeta.THREAD.getPlayers()) {
            ItemStack var4 = var3.getMainHandStack();
            Item var5 = var4.getItem();
            BlockItem var6;
            if (!(var5 instanceof BlockItem) || !((var6 = (BlockItem)var5).getBlock() instanceof ShulkerBoxBlock)) {
               var4 = var3.getOffHandStack();
            }

            if ((var5 = var4.getItem()) instanceof BlockItem && (var6 = (BlockItem)var5).getBlock() instanceof ShulkerBoxBlock) {
               this.map.put(var3.getGameProfile().getId(), new ShulkerViewer.Shulker(var4, var3.getGameProfile().getName()));
            }
         }
      }
   }

   @Override
   public void onRender2D(DrawContext drawContext, float tickDelta) {
      if (this.peek.getValue()) {
         offset = 0;
         this.map.values().removeIf(shulker -> shulker.draw(drawContext));
      }
   }

   static {

      ITEMS = new ItemStack[27];
   }
@Environment(EnvType.CLIENT)
   class Shulker {
      final ItemStack itemStack;
      final String name;
      private final Timer timer;

      public Shulker(ItemStack itemStack, String name) {
         this.itemStack = itemStack;
         this.timer = new Timer();
         this.name = name;
      }

      public boolean draw(DrawContext context) {
         if (this.timer.passedS(ShulkerViewer.this.renderTime.getValue())) {
            return true;
         } else {
            ShulkerViewer.renderShulkerToolTip(
               context, ShulkerViewer.this.xOffset.getValueInt() - 8, ShulkerViewer.this.yOffset.getValueInt() + ShulkerViewer.offset, this.itemStack
            );
            TextRenderer var2 = Wrapper.mc.textRenderer;
            int var3 = ShulkerViewer.this.xOffset.getValueInt();
            int var4 = ShulkerViewer.this.yOffset.getValueInt() + ShulkerViewer.offset;
            Objects.requireNonNull(Wrapper.mc.textRenderer);
            context.drawText(var2, this.name, var3, var4 - 9 - 82, -1, false);
            ShulkerViewer.offset = ShulkerViewer.offset + ShulkerViewer.this.space.getValueInt();
            return false;
         }
      }
   }
}
