package dev.crucifixbeta.mod.gui.clickgui;

import com.mojang.blaze3d.systems.RenderSystem;
import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.api.utils.math.Animation;
import dev.crucifixbeta.api.utils.math.Easing;
import dev.crucifixbeta.api.utils.render.ColorUtil;
import dev.crucifixbeta.api.utils.render.Render2DUtil;
import dev.crucifixbeta.api.utils.render.TextUtil;
import dev.crucifixbeta.core.impl.CommandManager;
import dev.crucifixbeta.core.impl.FontManager;
import dev.crucifixbeta.mod.Mod;
import dev.crucifixbeta.mod.gui.clickgui.pages.ClickGuiConfigPage;
import dev.crucifixbeta.mod.gui.clickgui.pages.ClickGuiHudPage;
import dev.crucifixbeta.mod.gui.clickgui.pages.ClickGuiModulePage;
import dev.crucifixbeta.mod.gui.items.Component;
import dev.crucifixbeta.mod.gui.items.Item;
import dev.crucifixbeta.mod.gui.items.buttons.ModuleButton;
import dev.crucifixbeta.mod.gui.windows.WindowBase;
import dev.crucifixbeta.mod.modules.HudModule;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.impl.client.ClickGui;
import dev.crucifixbeta.mod.modules.impl.client.ClientSetting;
import dev.crucifixbeta.mod.modules.impl.client.ColorsModule;
import dev.crucifixbeta.mod.modules.impl.client.hud.HudSetting;
import dev.crucifixbeta.mod.modules.impl.render.AntiAlias;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.util.InputUtil;
import net.minecraft.text.Text;

@Environment(EnvType.CLIENT)
public class ClickGuiScreen extends Screen {
   public static final Comparator<Mod> MODULE_NAME_COMPARATOR;
   private static ClickGuiScreen INSTANCE;
   private static final int CATEGORY_WIDTH;
   private static final int CATEGORY_HEADER_HEIGHT;
   private static final int CATEGORY_SPACING;
   private static final int SEARCH_WIDTH;
   private static final int SEARCH_HEIGHT;
   private static final int PAGE_TAB_WIDTH;
   private static final int PAGE_TAB_HEIGHT;
   private final ArrayList<Component> components = new ArrayList<>();
   private final ArrayList<ClickGuiScreen.TopTab> tabs = new ArrayList<>();
   private final Map<String, Integer> textWidthCache = new HashMap<>();
   private final Map<HudModule, Animation> hudHoverAnimations = new IdentityHashMap<>();
   private final ClickGuiConfigPage configPage = new ClickGuiConfigPage(this);
   private final ClickGuiHudPage hudPage = new ClickGuiHudPage(this);
   private final ClickGuiModulePage modulePage = new ClickGuiModulePage(this);
   private final ClickGuiFrame reusableFrame = new ClickGuiFrame();
   private ClickGuiFrame lastFrame;
   private ClickGuiScreen.Page page = ClickGuiScreen.Page.Module;
   private int loadedModuleCount = -1;
   private int lastLayoutScreenW = -1;
   private int lastLayoutScreenH = -1;
   private boolean layoutCorrected;
   private String searchText = "";
   private boolean searchFocused;
   private int searchX;
   private int searchY;
   private int searchW = 190;
   private int searchH = 22;
   private boolean confirmOpen;
   private String confirmTitle;
   private String confirmMessage;
   private Runnable confirmYesAction;
   private int tabX;
   private int tabY;
   private int tabW;
   private int tabH;

   public ClickGuiScreen() {
      super(Text.empty());
      INSTANCE = this;
      this.load();
   }

   public static ClickGuiScreen getInstance() {
      if (INSTANCE == null) {
         INSTANCE = new ClickGuiScreen();
      }

      return INSTANCE;
   }

   private void load() {
      this.loadedModuleCount = CrucifixBeta.MODULE != null ? CrucifixBeta.MODULE.getModules().size() : -1;
      this.components.clear();
      this.tabs.clear();
      this.tabs.add(new ClickGuiScreen.TopTab(ClickGuiScreen.Page.Module, "Module"));
      this.tabs.add(new ClickGuiScreen.TopTab(ClickGuiScreen.Page.Config, "Params"));
      this.tabs.add(new ClickGuiScreen.TopTab(ClickGuiScreen.Page.Hud, "HUD"));
      int var1 = 0;

      for (final Module.Category var5 : Module.Category.values()) {
         if (this.shouldShowCategory(var5)) {
            Component var6 = new Component(this.getCategoryTitle(var5), var5, 0, 0, true) {
               @Override
               public void setupItems() {
                  for (Module var2 : CrucifixBeta.MODULE.getModules()) {
                     if (var2.getCategory().equals(var5) && !ClickGuiScreen.this.isHudComponentModule(var2)) {
                        this.addButton(new ModuleButton(var2));
                     }
                  }
               }
            };
            var6.setWidth(110);
            var6.setHeight(25);
            var6.setOpenAnimationIndex(var1++);
            var6.getItems().sort(MODULE_NAME_COMPARATOR);
            this.components.add(var6);
         }
      }

      this.textWidthCache.clear();
      this.layoutCorrected = false;
      this.applySearchFilter();
      this.hudPage.init();
   }

   public void reload() {
      this.load();
   }

   public void reloadIfModuleListChanged() {
      int var1 = CrucifixBeta.MODULE != null ? CrucifixBeta.MODULE.getModules().size() : -1;
      if (var1 != this.loadedModuleCount) {
         this.reload();
      }
   }

   @Override
   public void render(DrawContext context, int mouseX, int mouseY, float delta) {
      ClickGui var5 = ClickGui.getInstance();
      if (var5 != null) {
         this.reloadIfModuleListChanged();
         Item.context = context;
         var5.updateColor();
         AntiAlias.beginClickGuiAA();

         try {
            RenderSystem.defaultBlendFunc();
            RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, (float)var5.alphaValue);
            Render2DUtil.drawRect(
               context.getMatrices(), 0.0F, 0.0F, (float)context.getScaledWindowWidth(), (float)context.getScaledWindowHeight(), new Color(0, 0, 0, 76)
            );
            var5.renderSnow(context);
            switch (this.page) {
               case Module:
                  this.renderModulePage(context, mouseX, mouseY, delta);
                  break;
               case Config:
                  this.renderConfigPage(context, mouseX, mouseY, delta);
                  break;
               case Hud:
                  this.renderHudPage(context, mouseX, mouseY, delta);
                  break;
               case AiAssistant:
                  this.renderModulePage(context, mouseX, mouseY, delta);
            }

            this.renderPageTabs(context, mouseX, mouseY, var5);
            if (this.confirmOpen) {
               this.renderConfirmDialog(context, mouseX, mouseY, var5, ClientSetting.INSTANCE);
            }
         } finally {
            RenderSystem.defaultBlendFunc();
            RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
            AntiAlias.endClickGuiAA();
         }
      }
   }

   private void renderModulePage(DrawContext context, int mouseX, int mouseY, float delta) {
      this.renderSearchBar(context, mouseX, mouseY);
      this.applySearchFilter();
      this.layoutModulesIfNeeded(context.getScaledWindowWidth(), context.getScaledWindowHeight());
      int var5 = 0;

      for (Component var7 : this.components) {
         if (!var7.isHidden()) {
            var5++;
            var7.drawScreen(context, mouseX, mouseY, delta);
         }
      }

      if (var5 == 0) {
         String var8 = "No matches";
         float var9 = (float)(context.getScaledWindowWidth() - this.getTextWidth(var8)) / 2.0F;
         TextUtil.drawString(
            context,
            var8,
            (double)var9,
            (double)(this.searchY + this.searchH + 28),
            ColorUtil.injectAlpha(-1, 180),
            FontManager.isCustomFontEnabled(),
            FontManager.isShadowEnabled()
         );
      }
   }

   private void renderConfigPage(DrawContext context, int mouseX, int mouseY, float delta) {
      this.prepareFrame(context);
      this.configPage.render(context, mouseX, mouseY, delta, this.reusableFrame);
   }

   private void renderHudPage(DrawContext context, int mouseX, int mouseY, float delta) {
      this.renderHudModules(context, delta);
      this.prepareFrame(context);
      this.hudPage.render(context, mouseX, mouseY, delta, this.reusableFrame);
      this.renderHudHoverOverlay(context, mouseX, mouseY);
   }

   private void prepareFrame(DrawContext context) {
      int var2 = context.getScaledWindowWidth();
      int var3 = context.getScaledWindowHeight();
      this.reusableFrame.set(1.0F, 0.0F, 0.0F, var2, 0, 0, var2, var3, 0.0F, 0.0F, var2, var3);
      this.lastFrame = this.reusableFrame;
   }

   private void renderHudModules(DrawContext context, float delta) {
      if (CrucifixBeta.MODULE != null) {
         for (Module var4 : CrucifixBeta.MODULE.getModules()) {
            if (var4 instanceof HudModule && var4.isOn()) {
               try {
                  HudModule var5 = (HudModule)var4;
                  var5.beginScaledRender(context);

                  try {
                     var4.onRender2D(context, delta);
                  } finally {
                     var5.endScaledRender(context);
                  }

                  if (var5.getHudBoundW() <= 0 || var5.getHudBoundH() <= 0) {
                     this.renderHudEditPreview(context, var5);
                  }
               } catch (Exception var10) {
                  var10.printStackTrace();
                  if (ClientSetting.INSTANCE != null && ClientSetting.INSTANCE.debug.getValue()) {
                     CommandManager.sendMessage("Error in " + var4.getName() + " [onRender2D]: " + var10.getMessage());
                  }
               }
            }
         }
      }
   }

   private void renderHudEditPreview(DrawContext context, HudModule module) {
      String var3 = module.getDisplayName();
      boolean var4 = HudSetting.useFont() && FontManager.ui != null;
      int var5 = var4 ? (int)Math.ceil((double)FontManager.ui.getWidth(var3)) : (int)Math.ceil((double)TextUtil.getWidth(var3));
      int var6 = var4 ? (int)Math.ceil((double)FontManager.ui.getFontHeight()) : (int)Math.ceil((double)TextUtil.getHeight());
      int var7 = Math.max(56, var5 + 14);
      int var8 = Math.max(18, var6 + 8);
      int var9 = module.getHudRenderX(var7);
      int var10 = module.getHudRenderY(var8);
      Color var11 = ClickGui.getInstance() == null ? new Color(224, 80, 255, 150) : ColorUtil.injectAlpha(ClickGui.getInstance().hoverColor.getValue(), 150);
      Color var12 = ClickGui.getInstance() == null ? new Color(20, 20, 24, 145) : ColorUtil.injectAlpha(ClickGui.getInstance().defaultColor.getValue(), 145);
      module.beginScaledRender(context);

      try {
         var9 = module.getHudRenderX(var7);
         var10 = module.getHudRenderY(var8);
         Render2DUtil.drawRoundedRect(context.getMatrices(), (float)var9, (float)var10, (float)var7, (float)var8, 5.0F, var12);
         Render2DUtil.drawRoundedStroke(context.getMatrices(), (float)var9, (float)var10, (float)var7, (float)var8, 5.0F, var11, 12);
         TextUtil.drawString(context, var3, (double)(var9 + 7), (double)var10 + (double)(var8 - var6) / 2.0, Color.WHITE.getRGB(), var4, HudSetting.useShadow());
         module.setHudEditBounds(var9, var10, var7, var8);
      } finally {
         module.endScaledRender(context);
      }
   }

   private void renderHudHoverOverlay(DrawContext context, int mouseX, int mouseY) {
      if (CrucifixBeta.MODULE == null) {
         this.hudHoverAnimations.clear();
      } else {
         for (Module var5 : CrucifixBeta.MODULE.getModules()) {
            if (var5 instanceof HudModule) {
               HudModule var6 = (HudModule)var5;
               if (var5.isOn() && var6.getHudBoundW() > 0 && var6.getHudBoundH() > 0) {
                  Animation var7 = this.hudHoverAnimations.computeIfAbsent(var6, ignored -> new Animation());
                  double var8 = var7.get(var6.isHudHit(mouseX, mouseY) ? 1.0 : 0.0, 170L, Easing.CubicInOut);
                  if (!(var8 <= 0.01)) {
                     float var10 = (float)var6.getHudBoundX() - 3.0F;
                     float var11 = (float)var6.getHudBoundY() - 3.0F;
                     float var12 = (float)var6.getHudBoundW() + 6.0F;
                     float var13 = (float)var6.getHudBoundH() + 6.0F;
                     ClickGui var14 = ClickGui.getInstance();
                     Color var15 = var14 == null ? new Color(224, 80, 255) : var14.hoverColor.getValue();
                     Render2DUtil.drawRoundedRect(context.getMatrices(), var10, var11, var12, var13, 5.0F, ColorUtil.injectAlpha(var15, (int)(28.0 * var8)));
                     Render2DUtil.drawRoundedStroke(
                        context.getMatrices(), var10, var11, var12, var13, 5.0F, ColorUtil.injectAlpha(var15, (int)(205.0 * var8)), 12
                     );
                     String var16 = var5.getDisplayName();
                     boolean var17 = HudSetting.useFont() && FontManager.ui != null;
                     int var18 = var17 ? (int)Math.ceil((double)FontManager.ui.getWidth(var16)) : (int)Math.ceil((double)TextUtil.getWidth(var16));
                     int var19 = var17 ? (int)Math.ceil((double)FontManager.ui.getFontHeight()) : (int)Math.ceil((double)TextUtil.getHeight());
                     float var20 = (float)var18 + 12.0F;
                     float var21 = Math.max(17.0F, (float)var19 + 8.0F);
                     float var22 = var10 + var12 + 7.0F - (float)((1.0 - var8) * 4.0);
                     if (var22 + var20 > (float)context.getScaledWindowWidth() - 4.0F) {
                        var22 = var10 - var20 - 7.0F + (float)((1.0 - var8) * 4.0);
                     }

                     float var23 = var11 + Math.max(0.0F, (var13 - var21) / 2.0F);
                     var23 = Math.max(4.0F, Math.min(var23, (float)context.getScaledWindowHeight() - var21 - 4.0F));
                     Color var24 = var14 == null ? new Color(15, 15, 18) : var14.defaultColor.getValue();
                     Render2DUtil.drawRoundedRect(context.getMatrices(), var22, var23, var20, var21, 5.0F, ColorUtil.injectAlpha(var24, (int)(210.0 * var8)));
                     Render2DUtil.drawRoundedStroke(
                        context.getMatrices(), var22, var23, var20, var21, 5.0F, ColorUtil.injectAlpha(var15, (int)(135.0 * var8)), 12
                     );
                     TextUtil.drawString(
                        context,
                        var16,
                        (double)(var22 + 6.0F),
                        (double)(var23 + (var21 - (float)var19) / 2.0F),
                        ColorUtil.injectAlpha(Color.WHITE, (int)(255.0 * var8)).getRGB(),
                        var17,
                        HudSetting.useShadow()
                     );
                  }
               }
            }
         }

         Iterator var25 = this.hudHoverAnimations.entrySet().iterator();

         while (var25.hasNext()) {
            Entry var26 = (Entry)var25.next();
            HudModule var27 = (HudModule)var26.getKey();
            if (var27.isOff() && ((Animation)var26.getValue()).get(0.0, 170L, Easing.CubicInOut) <= 0.001) {
               var25.remove();
            }
         }
      }
   }

   private void layoutModulesIfNeeded(int screenWidth, int screenHeight) {
      if (!this.layoutCorrected || screenWidth != this.lastLayoutScreenW || screenHeight != this.lastLayoutScreenH) {
         this.lastLayoutScreenW = screenWidth;
         this.lastLayoutScreenH = screenHeight;
         int var3 = 0;

         for (Component var5 : this.components) {
            if (!var5.isHidden()) {
               var3++;
            }
         }

         if (var3 == 0) {
            var3 = this.components.size();
         }

         int var9 = var3 * 110 + Math.max(0, var3 - 1) * 10;
         int var10 = Math.round((float)(screenWidth - var9) / 2.0F);
         int var6 = this.searchY + this.searchH + 12;

         for (Component var8 : this.components) {
            if (!var8.isHidden()) {
               var8.setX(var10);
               var8.setY(var6);
               var8.setWidth(110);
               var8.setHeight(25);
               var10 += 120;
            }
         }

         this.layoutCorrected = true;
      }
   }

   private void renderSearchBar(DrawContext context, int mouseX, int mouseY) {
      this.searchW = 190;
      this.searchH = 22;
      this.searchX = (context.getScaledWindowWidth() - this.searchW) / 2;
      this.searchY = 18;
      boolean var4 = isHovered((double)this.searchX, (double)this.searchY, (double)this.searchW, (double)this.searchH, (double)mouseX, (double)mouseY);
      Color var5 = ClickGui.getInstance().getActiveColor(0.0);
      Color var6 = this.applyDesignAlpha(var5, !this.searchFocused && !var4 ? 58 : 160);
      Color var7 = new Color(15, 15, 15, !this.searchFocused && !var4 ? 198 : 218);
      Render2DUtil.drawRoundedRect(context.getMatrices(), (float)this.searchX, (float)this.searchY, (float)this.searchW, (float)this.searchH, 10.0F, var7);
      Render2DUtil.drawRoundedStroke(context.getMatrices(), (float)this.searchX, (float)this.searchY, (float)this.searchW, (float)this.searchH, 10.0F, var6, 16);
      boolean var8 = this.searchText.isEmpty() && !this.searchFocused;
      String var9 = this.searchFocused && System.currentTimeMillis() / 500L % 2L == 0L ? "_" : "";
      String var10 = var8 ? "Search" : this.searchText + var9;
      int var11 = var8 ? -6645094 : -1;
      TextUtil.drawString(
         context, var10, (double)(this.searchX + 9), (double)(this.searchY + 7), var11, FontManager.isCustomFontEnabled(), FontManager.isShadowEnabled()
      );
   }

   private void renderPageTabs(DrawContext context, int mouseX, int mouseY, ClickGui gui) {
      this.tabH = 21;
      this.tabW = 42 * this.tabs.size();
      this.tabX = context.getScaledWindowWidth() - this.tabW - 8;
      this.tabY = context.getScaledWindowHeight() - this.tabH - 8;
      Color var5 = gui.getActiveColor((double)this.tabY * 0.25);
      Render2DUtil.drawRoundedRect(
         context.getMatrices(), (float)this.tabX, (float)this.tabY, (float)this.tabW, (float)this.tabH, 7.0F, new Color(21, 21, 21, 220)
      );
      int var6 = 0;

      for (int var7 = 0; var7 < this.tabs.size(); var7++) {
         if (this.tabs.get(var7).page == this.page) {
            var6 = var7;
            break;
         }
      }

      Render2DUtil.drawRoundedRect(
         context.getMatrices(),
         (float)(this.tabX + 2 + var6 * 42),
         (float)(this.tabY + 2),
         38.0F,
         (float)(this.tabH - 4),
         6.0F,
         this.applyDesignAlpha(var5, 160)
      );
      Render2DUtil.drawRoundedStroke(
         context.getMatrices(), (float)this.tabX, (float)this.tabY, (float)this.tabW, (float)this.tabH, 7.0F, this.applyDesignAlpha(var5, 70), 16
      );

      for (int var13 = 1; var13 < this.tabs.size(); var13++) {
         int var8 = this.tabX + var13 * 42;
         Render2DUtil.drawRect(context.getMatrices(), (float)var8, (float)(this.tabY + 5), 1.0F, (float)(this.tabH - 10), new Color(255, 255, 255, 22));
      }

      for (int var14 = 0; var14 < this.tabs.size(); var14++) {
         ClickGuiScreen.TopTab var15 = this.tabs.get(var14);
         int var9 = this.tabX + var14 * 42;
         boolean var10 = isHovered((double)var9, (double)this.tabY, 42.0, (double)this.tabH, (double)mouseX, (double)mouseY);
         int var11 = this.page != var15.page && !var10 ? -6645094 : -1;
         int var12 = this.getTextWidth(var15.label);
         TextUtil.drawString(
            context,
            var15.label,
            (double)((float)var9 + (float)(42 - var12) / 2.0F),
            (double)(this.tabY + 7),
            var11,
            FontManager.isCustomFontEnabled(),
            FontManager.isShadowEnabled()
         );
      }
   }

   @Override
   public boolean mouseClicked(double mouseX, double mouseY, int button) {
      if (this.confirmOpen) {
         return this.handleConfirmClick((int)mouseX, (int)mouseY, button);
      } else if (button == 0 && this.handlePageTabClick(mouseX, mouseY)) {
         return true;
      } else if (this.page == ClickGuiScreen.Page.Module) {
         if (button == 0 && isHovered((double)this.searchX, (double)this.searchY, (double)this.searchW, (double)this.searchH, mouseX, mouseY)) {
            this.searchFocused = true;
            return true;
         } else {
            if (button == 0) {
               this.searchFocused = false;
            }

            for (Component var7 : this.components) {
               if (!var7.isHidden()) {
                  var7.mouseClicked((int)mouseX, (int)mouseY, button);
               }
            }

            return true;
         }
      } else {
         if (this.page == ClickGuiScreen.Page.Config) {
            ClickGuiFrame var6 = this.lastFrame;
            if (var6 != null && this.configPage.mouseClicked((int)mouseX, (int)mouseY, button, var6)) {
               return true;
            }
         } else if (this.page == ClickGuiScreen.Page.Hud) {
            ClickGuiFrame var8 = this.lastFrame;
            if (var8 != null && this.hudPage.mouseClicked((int)mouseX, (int)mouseY, button, var8)) {
               return true;
            }
         }

         return super.mouseClicked(mouseX, mouseY, button);
      }
   }

   @Override
   public boolean mouseReleased(double mouseX, double mouseY, int button) {
      if (this.page == ClickGuiScreen.Page.Module) {
         for (Component var7 : this.components) {
            if (!var7.isHidden()) {
               var7.mouseReleased((int)mouseX, (int)mouseY, button);
            }
         }
      } else if (this.page == ClickGuiScreen.Page.Hud) {
         ClickGuiFrame var9 = this.lastFrame;
         int var10 = var9 != null ? (int)var9.unitMouseX((int)mouseX) : (int)mouseX;
         int var8 = var9 != null ? (int)var9.unitMouseY((int)mouseY) : (int)mouseY;
         this.hudPage.mouseReleased(var10, var8, button);
      }

      return super.mouseReleased(mouseX, mouseY, button);
   }

   @Override
   public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
      if (this.page == ClickGuiScreen.Page.Module) {
         this.modulePage.mouseScrolled(mouseX, mouseY, verticalAmount);
      } else if (this.page == ClickGuiScreen.Page.Config) {
         if (Wrapper.mc != null && Wrapper.mc.getWindow() != null) {
            this.configPage.mouseScrolled(verticalAmount, Wrapper.mc.getWindow().getScaledHeight());
         }
      } else if (this.page == ClickGuiScreen.Page.Hud) {
         this.hudPage.mouseScrolled(verticalAmount);
      }

      return true;
   }

   @Override
   public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
      if (this.confirmOpen) {
         if (keyCode == 256) {
            this.closeConfirm();
            return true;
         } else if (keyCode != 257 && keyCode != 335) {
            return true;
         } else {
            this.confirmYes();
            return true;
         }
      } else if (keyCode == 256) {
         if (this.page == ClickGuiScreen.Page.Module && this.handleSearchKey(keyCode)) {
            return true;
         } else if (this.page == ClickGuiScreen.Page.Config && this.configPage.keyPressed(keyCode)) {
            return true;
         } else if (this.page == ClickGuiScreen.Page.Hud && this.hudPage.keyPressed(keyCode)) {
            return true;
         } else {
            this.close();
            return true;
         }
      } else if (this.page == ClickGuiScreen.Page.Module) {
         if (this.handleSearchKey(keyCode)) {
            return true;
         } else {
            this.components.forEach(component -> component.onKeyPressed(keyCode));
            return super.keyPressed(keyCode, scanCode, modifiers);
         }
      } else if (this.page == ClickGuiScreen.Page.Hud) {
         return this.hudPage.keyPressed(keyCode) ? true : super.keyPressed(keyCode, scanCode, modifiers);
      } else {
         return this.page == ClickGuiScreen.Page.Config && this.configPage.keyPressed(keyCode) ? true : super.keyPressed(keyCode, scanCode, modifiers);
      }
   }

   @Override
   public boolean charTyped(char chr, int modifiers) {
      if (this.page == ClickGuiScreen.Page.Module) {
         if (this.searchFocused && !Character.isISOControl(chr)) {
            this.searchText = this.searchText + chr;
            this.layoutCorrected = false;
            return true;
         } else {
            this.components.forEach(component -> component.onKeyTyped(chr, modifiers));
            return super.charTyped(chr, modifiers);
         }
      } else if (this.page == ClickGuiScreen.Page.Hud) {
         this.hudPage.charTyped(chr, modifiers);
         return super.charTyped(chr, modifiers);
      } else {
         return this.page == ClickGuiScreen.Page.Config && this.configPage.charTyped(chr) ? true : super.charTyped(chr, modifiers);
      }
   }

   private boolean handleSearchKey(int keyCode) {
      if (!this.searchFocused) {
         return false;
      } else if (keyCode == 256 || keyCode == 257 || keyCode == 335) {
         this.searchFocused = false;
         return true;
      } else if (keyCode == 259) {
         this.searchText = removeLastCodePoint(this.searchText);
         this.layoutCorrected = false;
         return true;
      } else if (keyCode == 65 && Wrapper.mc != null && Wrapper.mc.getWindow() != null && InputUtil.isKeyPressed(Wrapper.mc.getWindow().getHandle(), 341)) {
         this.searchText = "";
         this.layoutCorrected = false;
         return true;
      } else {
         return false;
      }
   }

   private void applySearchFilter() {
      String var1 = normalizeSearch(this.searchText);
      boolean var2 = var1.isEmpty();

      for (Component var4 : this.components) {
         boolean var5 = var2;

         for (ModuleButton var7 : var4.getItems()) {
            boolean var8 = var2 || this.matchesSearch(var7.getModule(), var1);
            var7.setHidden(!var8);
            if (var8) {
               var5 = true;
            }
         }

         var4.setHidden(!var5);
      }
   }

   private boolean matchesSearch(Module module, String query) {
      return normalizeSearch(module.getName()).contains(query)
         || normalizeSearch(module.getDisplayName()).contains(query)
         || normalizeSearch(module.getChineseName()).contains(query)
         || normalizeSearch(module.getInfo()).contains(query);
   }

   private boolean handlePageTabClick(double mouseX, double mouseY) {
      for (int var5 = 0; var5 < this.tabs.size(); var5++) {
         int var6 = this.tabX + var5 * 42;
         if (isHovered((double)var6, (double)this.tabY, 42.0, (double)this.tabH, mouseX, mouseY)) {
            this.setPage(this.tabs.get(var5).page);
            return true;
         }
      }

      return false;
   }

   private void setPage(ClickGuiScreen.Page page) {
      this.setPage(page, true);
   }

   private void setPage(ClickGuiScreen.Page page, boolean resetHud) {
      if (page != null) {
         this.page = page;
         this.searchFocused = false;

         for (Component var4 : this.components) {
            var4.drag = false;
         }

         this.configPage.stopNameListening();
         if (page == ClickGuiScreen.Page.Config) {
            this.configPage.onOpen();
         }

         if (page == ClickGuiScreen.Page.Hud && resetHud) {
            this.hudPage.resetHudLayout();
         }
      }
   }

   public void openHudWindow(WindowBase window) {
      this.hudPage.openHudWindow(window);
      this.setPage(ClickGuiScreen.Page.Hud, false);
   }

   public void openConfirm(String title, String msg, Runnable yesAction) {
      this.confirmOpen = true;
      this.confirmTitle = title;
      this.confirmMessage = msg;
      this.confirmYesAction = yesAction;
      this.configPage.stopNameListening();
   }

   private void renderConfirmDialog(DrawContext context, int mouseX, int mouseY, ClickGui gui, ClientSetting clientSetting) {
      boolean var6 = clientSetting != null && clientSetting.chinese.getValue();
      int var7 = context.getScaledWindowWidth();
      int var8 = context.getScaledWindowHeight();
      Render2DUtil.drawRect(context.getMatrices(), 0.0F, 0.0F, (float)var7, (float)var8, new Color(0, 0, 0, 95));
      int var9 = Math.min(340, var7 - 40);
      byte var10 = 104;
      int var11 = (var7 - var9) / 2;
      int var12 = (var8 - var10) / 2;
      Render2DUtil.drawRoundedRect(context.getMatrices(), (float)var11, (float)var12, (float)var9, (float)var10, 8.0F, new Color(15, 15, 15, 230));
      Render2DUtil.drawRoundedStroke(
         context.getMatrices(), (float)var11, (float)var12, (float)var9, (float)var10, 8.0F, this.applyDesignAlpha(gui.getActiveColor((double)var12), 90), 16
      );
      String var13 = this.confirmTitle != null && !this.confirmTitle.isEmpty()
         ? this.confirmTitle
         : (var6 ? "Confirm" : "Confirm");
      String var14 = this.confirmMessage == null ? "" : this.confirmMessage;
      TextUtil.drawString(context, var13, (double)(var11 + 12), (double)(var12 + 16), -1, FontManager.isCustomFontEnabled(), FontManager.isShadowEnabled());
      TextUtil.drawString(
         context, var14, (double)(var11 + 12), (double)(var12 + 36), -5197648, FontManager.isCustomFontEnabled(), FontManager.isShadowEnabled()
      );
      int var15 = var12 + var10 - 30;
      int var16 = (var9 - 32) / 2;
      this.drawConfirmButton(context, mouseX, mouseY, var11 + 12, var15, var16, 20, var6 ? "Yes" : "Yes", true);
      this.drawConfirmButton(
         context, mouseX, mouseY, var11 + 20 + var16, var15, var16, 20, var6 ? "No" : "No", false
      );
   }

   private void drawConfirmButton(DrawContext context, int mouseX, int mouseY, int x, int y, int w, int h, String text, boolean accent) {
      boolean var10 = isHovered((double)x, (double)y, (double)w, (double)h, (double)mouseX, (double)mouseY);
      Color var11 = accent
         ? this.applyDesignAlpha(ClickGui.getInstance().getActiveColor((double)y), var10 ? 190 : 150)
         : new Color(28, 28, 28, var10 ? 235 : 210);
      Render2DUtil.drawRoundedRect(context.getMatrices(), (float)x, (float)y, (float)w, (float)h, 6.0F, var11);
      int var12 = this.getTextWidth(text);
      TextUtil.drawString(
         context, text, (double)((float)x + (float)(w - var12) / 2.0F), (double)(y + 6), -1, FontManager.isCustomFontEnabled(), FontManager.isShadowEnabled()
      );
   }

   private boolean handleConfirmClick(int mx, int my, int button) {
      if (button != 0) {
         this.closeConfirm();
         return true;
      } else {
         int var4 = Wrapper.mc != null && Wrapper.mc.getWindow() != null ? Wrapper.mc.getWindow().getScaledWidth() : 0;
         int var5 = Wrapper.mc != null && Wrapper.mc.getWindow() != null ? Wrapper.mc.getWindow().getScaledHeight() : 0;
         int var6 = Math.min(340, var4 - 40);
         byte var7 = 104;
         int var8 = (var4 - var6) / 2;
         int var9 = (var5 - var7) / 2;
         int var10 = var9 + var7 - 30;
         int var11 = (var6 - 32) / 2;
         if (isHovered((double)(var8 + 12), (double)var10, (double)var11, 20.0, (double)mx, (double)my)) {
            this.confirmYes();
         } else {
            this.closeConfirm();
         }

         return true;
      }
   }

   private void closeConfirm() {
      this.confirmOpen = false;
      this.confirmTitle = null;
      this.confirmMessage = null;
      this.confirmYesAction = null;
   }

   private Color applyDesignAlpha(Color color, int alpha) {
      ColorsModule var3 = ColorsModule.INSTANCE;
      return var3 != null && var3.colorMode.getValue() == ColorsModule.ColorMode.Static ? color : ColorUtil.injectAlpha(color, alpha);
   }

   private void confirmYes() {
      if (this.confirmYesAction != null) {
         this.confirmYesAction.run();
      }

      this.closeConfirm();
   }

   @Override
   public boolean shouldPause() {
      return false;
   }

   @Override
   public void close() {
      this.configPage.stopNameListening();
      this.closeConfirm();

      for (Component var2 : this.components) {
         var2.drag = false;
      }

      if (Wrapper.mc != null && Wrapper.mc.currentScreen == this) {
         Wrapper.mc.setScreen(null);
      }

      ClickGui var3 = ClickGui.getInstance();
      if (var3 != null && var3.isOn()) {
         var3.disable();
      }
   }

   public ClickGuiScreen.Page getPage() {
      return this.page;
   }

   public final ArrayList<Component> getComponents() {
      return this.components;
   }

   public int getTextOffset() {
      return -ClickGui.getInstance().textOffset.getValueInt() - 6;
   }

   public int getSearchBarHeight() {
      return 22;
   }

   public void renderSearchBarInClientColumn(DrawContext context, int mouseX, int mouseY, float x, float y, float width) {
   }

   public int getFontHeight() {
      return FontManager.isCustomFontEnabled() ? (int)FontManager.ui.getFontHeight() : 9;
   }

   public int getTextWidth(String text) {
      String var2 = text == null ? "" : text;
      return this.textWidthCache
         .computeIfAbsent(
            var2,
            value -> FontManager.isCustomFontEnabled() ? (int)FontManager.ui.getWidth(value) : Wrapper.mc != null ? Wrapper.mc.textRenderer.getWidth(value) : 0
         );
   }

   public float getCenteredTextY(float baseY, float boxHeight) {
      return baseY + (boxHeight - (float)this.getFontHeight()) / 2.0F + (float)ClickGui.getInstance().textOffset.getValueInt();
   }

   private boolean isHudComponentModule(Module module) {
      return module instanceof HudModule || module instanceof HudSetting;
   }

   private boolean shouldShowCategory(Module.Category category) {
      return category == Module.Category.HUD ? false : category != Module.Category.Debug;
   }

   private String getCategoryTitle(Module.Category category) {
      return category == Module.Category.Debug ? "Debug" : category.name();
   }

   private static boolean isHovered(double x, double y, double w, double h, double mouseX, double mouseY) {
      return mouseX >= x && mouseX <= x + w && mouseY >= y && mouseY <= y + h;
   }

   private static String removeLastCodePoint(String value) {
      return value != null && !value.isEmpty() ? value.substring(0, value.offsetByCodePoints(value.length(), -1)) : "";
   }

   private static String normalizeSearch(String value) {
      return value == null ? "" : value.toLowerCase(Locale.ROOT).replace(" ", "");
   }

   private static String sortKey(String value) {
      return value == null ? "" : value.toLowerCase(Locale.ROOT);
   }

   static {

      PAGE_TAB_HEIGHT = 21;
      PAGE_TAB_WIDTH = 42;
      SEARCH_HEIGHT = 22;
      SEARCH_WIDTH = 190;
      CATEGORY_SPACING = 10;
      CATEGORY_HEADER_HEIGHT = 25;
      CATEGORY_WIDTH = 110;
      MODULE_NAME_COMPARATOR = Comparator.<Mod, String>comparing(mod -> sortKey(mod.getName())).thenComparing(Mod::getName);
      INSTANCE = new ClickGuiScreen();
   }
@Environment(EnvType.CLIENT)
   public static enum Page {
      Module,
      Config,
      Hud,
      AiAssistant;

}

   @Environment(EnvType.CLIENT)
   private static final class TopTab {
      private final ClickGuiScreen.Page page;
      private final String label;

      private TopTab(ClickGuiScreen.Page page, String label) {
         this.page = page;
         this.label = label;
      }
   }
}
