package wtf.opal.client.screen.click.dropdown;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ibm.icu.impl.Pair;
import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.mod.modules.HudModule;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
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.Click;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.input.CharInput;
import net.minecraft.client.input.KeyInput;
import net.minecraft.text.Text;
import org.lwjgl.glfw.GLFW;
import wtf.opal.client.Constants;
import wtf.opal.client.OpalClient;
import wtf.opal.client.feature.module.Module;
import wtf.opal.client.feature.module.ModuleCategory;
import wtf.opal.client.feature.module.property.Property;
import wtf.opal.client.renderer.NVGRenderer;
import wtf.opal.client.renderer.repository.FontRepository;
import wtf.opal.client.screen.click.dropdown.panel.CategoryPanel;
import wtf.opal.utility.player.PlayerUtility;
import wtf.opal.utility.render.ColorUtility;
import wtf.opal.utility.render.animation.Animation;
import wtf.opal.utility.render.animation.Easing;

@Environment(EnvType.CLIENT)
public final class DropdownClickGUI extends Screen {
   private final List<CategoryPanel> categoryPanelList = new ArrayList<>();
   private CategoryPanel hudCategoryPanel;
   public static boolean displayingBinds;
   public static boolean selectingBind;
   public static boolean typingString;
   private String searchText = "";
   private boolean searchFocused;
   private boolean closing;
   private boolean closeCompleted;
   private float searchX;
   private float searchY;
   private float searchWidth;
   private float searchHeight;
   private final Animation searchAnimation = new Animation(Easing.EASE_OUT_SINE, 160L);
   private DropdownClickGUI.ClickPage activePage = DropdownClickGUI.ClickPage.MODULE;
   private final Animation pageTabAnimation = new Animation(Easing.EASE_OUT_SINE, 180L);
   private final Animation pageTabsAnimation = new Animation(Easing.EASE_OUT_SINE, 180L);
   private float pageTabsAnimationValue;
   private float pageTabsX;
   private float pageTabsY;
   private float pageTabsWidth;
   private float pageTabsHeight;
   private float pageTabWidth;
   private float pageX;
   private float pageY;
   private float pageWidth;
   private float pageHeight;
   private String configInput = "default";
   private boolean configInputFocused;
   private String selectedConfig;
   private String configStatus = "";
   private long configStatusTime;
   private HudModule draggingHudModule;
   private int draggingHudOffsetX;
   private int draggingHudOffsetY;
   private final Map<HudModule, Animation> hudHoverAnimations = new IdentityHashMap<>();
   private static final Gson CONFIG_GSON;

   public DropdownClickGUI() {
      super(Text.empty());
   }

   @Override
   public void renderBackground(DrawContext context, int mouseX, int mouseY, float deltaTicks) {
   }

   @Override
   public void render(DrawContext context, int mouseX, int mouseY, float delta) {
      if (this.activePage != DropdownClickGUI.ClickPage.PARAMS) {
         ClickGuiBlur.update(delta);
      }

      boolean var5 = NVGRenderer.beginFrame();
      displayingBinds = PlayerUtility.isKeyPressed(258);
      ClickGuiAnimationConfig.applyClickGuiOpenClose(this.pageTabsAnimation, 180L, Easing.EASE_OUT_SINE);
      this.pageTabsAnimation.run(this.closing ? 0.0F : 1.0F);
      this.pageTabsAnimationValue = this.pageTabsAnimation.getValue();
      if (this.isCloseAnimationComplete()) {
         if (var5) {
            NVGRenderer.endFrameAndReset(true);
         }

         this.finishClose();
      } else {
         if (this.activePage == DropdownClickGUI.ClickPage.MODULE) {
            this.renderSearchBar(mouseX, mouseY);
            int var6 = this.categoryPanelList.size();

            for (int var7 = 0; var7 < var6; var7++) {
               CategoryPanel var8 = this.categoryPanelList.get(var7);
               float var9 = this.searchY + this.searchHeight + 12.0F;
               float var10 = 110.0F;
               float var11 = 10.0F;
               float var12 = 20.0F;
               float var13 = (float)var6 * 110.0F + (float)(var6 - 1) * 10.0F;
               float var14 = ((float)Constants.mc.getWindow().getScaledWidth() - var13) / 2.0F;
               float var15 = var14 + (float)var7 * 120.0F;
               var8.setSearchQuery(this.searchText);
               var8.setLayoutDimensions(var15, var9, 110.0F, 20.0F);
               var8.render(context, mouseX, mouseY, delta);
            }
         } else if (this.activePage == DropdownClickGUI.ClickPage.PARAMS) {
            this.renderParamsPage(mouseX, mouseY);
         } else {
            this.dragHudElements(mouseX, mouseY);
            this.renderHudEditPreviews(context);
            this.renderHudHoverOverlay(mouseX, mouseY);
            this.renderHudPage(context, mouseX, mouseY, delta);
         }

         this.renderPageTabs(mouseX, mouseY);
         if (var5) {
            NVGRenderer.endFrameAndReset(true);
         }
      }
   }

   private void renderSearchBar(int mouseX, int mouseY) {
      this.searchWidth = 190.0F;
      this.searchHeight = 22.0F;
      this.searchX = ((float)Constants.mc.getWindow().getScaledWidth() - this.searchWidth) / 2.0F;
      ClickGuiAnimationConfig.applyClickGuiOpenClose(this.searchAnimation, 160L, Easing.EASE_OUT_SINE);
      this.searchAnimation.run(this.closing ? 0.0F : 1.0F);
      float var3 = this.searchAnimation.getValue();
      this.searchY = 18.0F - (1.0F - var3) * 8.0F;
      if (!(var3 <= 0.01F)) {
         float var4 = 10.0F;
         boolean var5 = (float)mouseX >= this.searchX
            && (float)mouseX <= this.searchX + this.searchWidth
            && (float)mouseY >= this.searchY
            && (float)mouseY <= this.searchY + this.searchHeight;
         int var6 = ColorUtility.applyOpacity(ColorUtility.darker((Integer)ColorUtility.getClientTheme().first, 0.2F), 0.62F);
         int var7 = !this.searchFocused && !var5 ? ColorUtility.applyOpacity(-1, 0.12F) : var6;
         int var8 = ColorUtility.scaleOpacity(ColorUtility.getPanelBackgroundColor(), !this.searchFocused && !var5 ? 0.78F : 0.85F);
         NVGRenderer.globalAlpha(var3);
         NVGRenderer.roundedRect(this.searchX, this.searchY, this.searchWidth, this.searchHeight, 10.0F, ColorUtility.scaleOpacity(var8, 0.6F));
         NVGRenderer.roundedRectOutline(this.searchX, this.searchY, this.searchWidth, this.searchHeight, 10.0F, 1.2F, var7);
         boolean var9 = this.searchText.isEmpty() && !this.searchFocused;
         String var10 = this.searchFocused && System.currentTimeMillis() / 500L % 2L == 0L ? "_" : "";
         String var11 = var9 ? "Search" : this.searchText + var10;
         int var12 = var9 ? -8355712 : -1;
         NVGRenderer.scissor(
            this.searchX + 8.0F,
            this.searchY,
            this.searchWidth - 16.0F,
            this.searchHeight,
            () -> FontRepository.getFont("productsans-medium").drawString(var11, this.searchX + 9.0F, this.searchY + 14.0F, 8.0F, var12)
         );
         NVGRenderer.globalAlpha(1.0F);
      }
   }

   private void renderParamsPage(int mouseX, int mouseY) {
      this.preparePageBounds(350.0F, 188.0F);
      this.renderPageShell("Params");
      List var3 = this.getConfigNames();
      if (this.selectedConfig == null && !var3.isEmpty()) {
         this.selectedConfig = (String)var3.get(0);
      }

      float var4 = this.pageX + 10.0F;
      float var5 = this.pageY + 28.0F;
      float var6 = 145.0F;
      float var7 = 18.0F;
      float var8 = var4 + 145.0F + 10.0F;
      float var9 = this.pageWidth - (var8 - this.pageX) - 10.0F;
      this.drawText("Configs", var4 + 2.0F, this.pageY + 20.0F, 7.5F, -1);

      for (int var10 = 0; var10 < Math.min(var3.size(), 7); var10++) {
         String var11 = (String)var3.get(var10);
         float var12 = var5 + (float)var10 * 18.0F;
         boolean var13 = var11.equals(this.selectedConfig);
         boolean var14 = this.isHovered(var4, var12, 145.0F, 17.0F, (double)mouseX, (double)mouseY);
         int var15 = var13
            ? ColorUtility.applyOpacity(ColorUtility.darker((Integer)ColorUtility.getClientTheme().first, 0.2F), 0.38F)
            : ColorUtility.scaleOpacity(var14 ? ColorUtility.getModuleHoverColor() : ColorUtility.getModuleBackgroundColor(), var14 ? 0.65F : 0.52F);
         NVGRenderer.roundedRect(var4, var12, 145.0F, 17.0F, 6.0F, var15);
         NVGRenderer.roundedRectOutline(var4, var12, 145.0F, 17.0F, 6.0F, 1.0F, ColorUtility.applyOpacity(-1, !var13 && !var14 ? 0.05F : 0.1F));
         this.drawText(var11, var4 + 6.0F, var12 + 11.5F, 7.0F, var13 ? -1 : -8355712);
      }

      float var16 = this.pageY + 31.0F;
      this.drawText("Name", var8 + 2.0F, this.pageY + 20.0F, 7.5F, ColorUtility.getEnabledTextColor());
      NVGRenderer.roundedRect(var8, var16, var9, 20.0F, 7.0F, ColorUtility.scaleOpacity(ColorUtility.getPanelBackgroundColor(), 0.6F));
      NVGRenderer.roundedRectOutline(
         var8,
         var16,
         var9,
         20.0F,
         7.0F,
         1.2F,
         ColorUtility.applyOpacity(ColorUtility.darker((Integer)ColorUtility.getClientTheme().first, 0.2F), this.configInputFocused ? 0.42F : 0.2F)
      );
      String var17 = this.configInput
         + (this.configInputFocused && System.currentTimeMillis() / 500L % 2L == 0L ? "_" : "");
      this.drawText(var17.isEmpty() ? "default" : var17, var8 + 7.0F, var16 + 12.5F, 7.2F, this.configInput.isEmpty() ? -8355712 : -1);
      float var18 = var16 + 28.0F;
      this.drawButton("Save", var8, var18, var9, 18.0F, mouseX, mouseY);
      this.drawButton("Load", var8, var18 + 23.0F, var9, 18.0F, mouseX, mouseY);
      this.drawButton("Delete", var8, var18 + 46.0F, var9, 18.0F, mouseX, mouseY);
      String var19 = this.getConfigStatus();
      if (!var19.isEmpty()) {
         this.drawText(var19, var8 + 2.0F, var18 + 76.0F, 7.0F, -8355712);
      }
   }

   private void renderHudPage(DrawContext context, int mouseX, int mouseY, float delta) {
      if (this.hudCategoryPanel != null) {
         float var5 = 110.0F;
         float var6 = 20.0F;
         float var7 = 12.0F;
         float var8 = 53.0F + (1.0F - this.pageTabsAnimationValue) * 8.0F;
         this.hudCategoryPanel.setSearchQuery("");
         this.hudCategoryPanel.setLayoutDimensions(12.0F, var8, 110.0F, 20.0F);
         this.hudCategoryPanel.render(context, mouseX, mouseY, delta);
      }
   }

   private void preparePageBounds(float width, float height) {
      this.pageWidth = width;
      this.pageHeight = height;
      this.pageX = ((float)Constants.mc.getWindow().getScaledWidth() - this.pageWidth) / 2.0F;
      this.pageY = 53.0F + (1.0F - this.pageTabsAnimationValue) * 8.0F;
   }

   private void renderPageShell(String title) {
      if (!(this.pageTabsAnimationValue <= 0.01F)) {
         NVGRenderer.globalAlpha(this.pageTabsAnimationValue);
         NVGRenderer.roundedRect(
            this.pageX, this.pageY, this.pageWidth, this.pageHeight, 10.0F, ColorUtility.scaleOpacity(ColorUtility.getPanelBackgroundColor(), 0.55F)
         );
         NVGRenderer.roundedRectOutline(this.pageX, this.pageY, this.pageWidth, this.pageHeight, 10.0F, 1.5F, ColorUtility.applyOpacity(-1, 0.12F));
         this.drawText(title, this.pageX + 10.0F, this.pageY + 14.0F, 8.5F, -1);
      }
   }

   private void drawButton(String text, float x, float y, float width, float height, int mouseX, int mouseY) {
      boolean var8 = this.isHovered(x, y, width, height, (double)mouseX, (double)mouseY);
      int var9 = var8
         ? ColorUtility.applyOpacity(ColorUtility.darker((Integer)ColorUtility.getClientTheme().first, 0.2F), 0.45F)
         : ColorUtility.scaleOpacity(ColorUtility.getModuleBackgroundColor(), 0.65F);
      NVGRenderer.roundedRect(x, y, width, height, 7.0F, var9);
      NVGRenderer.roundedRectOutline(x, y, width, height, 7.0F, 1.2F, ColorUtility.applyOpacity(-1, var8 ? 0.15F : 0.08F));
      float var10 = 7.2F;
      float var11 = FontRepository.getFont("productsans-medium").getStringWidth(text, 7.2F);
      this.drawText(text, x + (width - var11) / 2.0F, y + 11.5F, 7.2F, -1);
   }

   private void drawText(String text, float x, float y, float size, int color) {
      FontRepository.getFont("productsans-medium").drawString(text, x, y, size, color);
   }

   private List<String> getConfigNames() {
      File var1 = this.getConfigFolder();
      File[] var2 = var1.listFiles((dir, name) -> name.endsWith(".json"));
      ArrayList<String> var3 = new ArrayList<>();
      if (var2 != null) {
         for (File var7 : var2) {
            String var8 = var7.getName();
            var3.add(var8.substring(0, var8.length() - 5));
         }
      }

      var3.sort(String::compareToIgnoreCase);
      return var3;
   }

   private File getConfigFolder() {
      File var1 = new File(Constants.mc.runDirectory, "opal" + File.separator + "gui-configs");
      if (!var1.exists()) {
         var1.mkdirs();
      }

      return var1;
   }

   private String sanitizeConfigName(String value) {
      String var2 = (value == null ? "" : value.trim().toLowerCase(Locale.ROOT))
         .replaceAll("[^a-z0-9_\\- ]", "")
         .replace(' ', '_');
      return var2.isEmpty() ? "default" : var2;
   }

   private File getConfigFile(String name) {
      return new File(this.getConfigFolder(), this.sanitizeConfigName(name) + ".json");
   }

   private void saveCurrentConfig(String rawName) {
      String var2 = this.sanitizeConfigName(rawName);
      JsonArray var3 = new JsonArray();

      for (Module var5 : OpalClient.getInstance().getModuleRepository().getModules()) {
         JsonObject var6 = new JsonObject();
         var6.addProperty("name", var5.getId());
         var6.addProperty("enabled", var5.isEnabled());
         var6.addProperty("visible", var5.isVisible());
         var6.add("properties", this.serializeProperties(var5.getPropertyList()));
         var3.add(var6);
      }

      try {
         Files.writeString(this.getConfigFile(var2).toPath(), CONFIG_GSON.toJson(var3));
         this.selectedConfig = var2;
         this.configInput = var2;
         this.setConfigStatus("Saved " + var2);
      } catch (IOException var7) {
         this.setConfigStatus("Save failed");
         var7.printStackTrace();
      }
   }

   private boolean loadConfig(String rawName) {
      String var2 = this.sanitizeConfigName(rawName);
      File var3 = this.getConfigFile(var2);
      if (!var3.exists()) {
         this.setConfigStatus("Missing " + var2);
         return false;
      } else {
         try {
            boolean var14;
            try (FileReader var4 = new FileReader(var3)) {
               for (JsonElement var7 : JsonParser.parseReader(var4).getAsJsonArray()) {
                  JsonObject var8 = var7.getAsJsonObject();
                  String var9 = var8.get("name").getAsString();
                  Module var10 = OpalClient.getInstance().getModuleRepository().getModule(var9);
                  if (var8.has("enabled") && var8.get("enabled").getAsBoolean() != var10.isEnabled()) {
                     var10.setEnabled(var8.get("enabled").getAsBoolean());
                  }

                  if (var8.has("visible")) {
                     var10.setVisible(var8.get("visible").getAsBoolean());
                  }

                  if (var8.has("properties")) {
                     this.applyProperties(var10.getPropertyList(), var8.getAsJsonArray("properties"));
                  }
               }

               this.selectedConfig = var2;
               this.configInput = var2;
               this.setConfigStatus("Loaded " + var2);
               var14 = true;
            }

            return var14;
         } catch (Exception var13) {
            this.setConfigStatus("Load failed");
            var13.printStackTrace();
            return false;
         }
      }
   }

   private void deleteConfig(String rawName) {
      String var2 = this.sanitizeConfigName(rawName);
      File var3 = this.getConfigFile(var2);
      if (var3.exists() && var3.delete()) {
         this.setConfigStatus("Deleted " + var2);
         if (var2.equals(this.selectedConfig)) {
            this.selectedConfig = null;
         }
      } else {
         this.setConfigStatus("Delete failed");
      }
   }

   private JsonArray serializeProperties(List<Property<?>> properties) {
      JsonArray var2 = new JsonArray();

      for (Property var4 : properties) {
         JsonObject var5 = new JsonObject();
         var5.addProperty("name", var4.getId());
         var5.add("value", this.serializePropertyValue(var4.getValue()));
         var2.add(var5);
      }

      return var2;
   }

   private JsonElement serializePropertyValue(Object value) {
      if (value instanceof Pair var9) {
         JsonObject var10 = new JsonObject();
         var10.addProperty("x", ((Number)var9.first).doubleValue());
         var10.addProperty("y", ((Number)var9.second).doubleValue());
         return var10;
      } else if (value instanceof List var8) {
         JsonArray var3 = new JsonArray();

         for (Object var5 : var8) {
            if (var5 instanceof Property var6) {
               JsonObject var7 = new JsonObject();
               var7.addProperty("name", var6.getId());
               var7.add("value", this.serializePropertyValue(var6.getValue()));
               var3.add(var7);
            }
         }

         return var3;
      } else {
         return value instanceof Enum var2 ? CONFIG_GSON.toJsonTree(var2.name()) : CONFIG_GSON.toJsonTree(value);
      }
   }

   private void applyProperties(List<Property<?>> properties, JsonArray jsonProperties) {
      for (JsonElement var4 : jsonProperties) {
         JsonObject var5 = var4.getAsJsonObject();
         String var6 = var5.get("name").getAsString();

         for (Property var8 : properties) {
            if (var6.equals(var8.getId()) || var6.equals(var8.getName())) {
               var8.applyValue(CONFIG_GSON.fromJson(var5.get("value"), Object.class));
               break;
            }
         }
      }
   }

   private void setConfigStatus(String status) {
      this.configStatus = status;
      this.configStatusTime = System.currentTimeMillis();
   }

   private String getConfigStatus() {
      return System.currentTimeMillis() - this.configStatusTime > 2500L ? "" : this.configStatus;
   }

   private boolean isHovered(float x, float y, float width, float height, double mouseX, double mouseY) {
      return mouseX >= (double)x && mouseX <= (double)(x + width) && mouseY >= (double)y && mouseY <= (double)(y + height);
   }

   private void renderPageTabs(int mouseX, int mouseY) {
      DropdownClickGUI.ClickPage[] var3 = DropdownClickGUI.ClickPage.VALUES;
      this.pageTabsHeight = 21.0F;
      this.pageTabWidth = 42.0F;
      this.pageTabsWidth = this.pageTabWidth * (float)var3.length;
      this.pageTabsX = (float)Constants.mc.getWindow().getScaledWidth() - this.pageTabsWidth - 8.0F;
      this.pageTabsY = (float)Constants.mc.getWindow().getScaledHeight() - this.pageTabsHeight - 8.0F;
      ClickGuiAnimationConfig.applyPageSwitch(this.pageTabAnimation, 180L, Easing.EASE_OUT_SINE);
      this.pageTabAnimation.run((float)this.activePage.ordinal());
      float var4 = this.pageTabsX + 2.0F + this.pageTabAnimation.getValue() * this.pageTabWidth;
      int var5 = ColorUtility.darker((Integer)ColorUtility.getClientTheme().first, 0.2F);
      this.pageTabsY = this.pageTabsY + (1.0F - this.pageTabsAnimationValue) * 10.0F;
      if (!(this.pageTabsAnimationValue <= 0.01F)) {
         NVGRenderer.globalAlpha(this.pageTabsAnimationValue);
         NVGRenderer.roundedRect(
            this.pageTabsX,
            this.pageTabsY,
            this.pageTabsWidth,
            this.pageTabsHeight,
            8.0F,
            ColorUtility.scaleOpacity(ColorUtility.getPanelBackgroundColor(), 0.58F)
         );
         NVGRenderer.roundedRect(
            var4, this.pageTabsY + 2.0F, this.pageTabWidth - 4.0F, this.pageTabsHeight - 4.0F, 6.0F, ColorUtility.applyOpacity(var5, 0.62F)
         );
         NVGRenderer.roundedRectOutline(
            this.pageTabsX, this.pageTabsY, this.pageTabsWidth, this.pageTabsHeight, 8.0F, 1.2F, ColorUtility.applyOpacity(-1, 0.1F)
         );

         for (int var6 = 1; var6 < var3.length; var6++) {
            float var7 = this.pageTabsX + (float)var6 * this.pageTabWidth;
            NVGRenderer.rect(var7, this.pageTabsY + 5.0F, 1.0F, this.pageTabsHeight - 10.0F, ColorUtility.applyOpacity(-1, 0.08F));
         }

         for (int var14 = 0; var14 < var3.length; var14++) {
            DropdownClickGUI.ClickPage var15 = var3[var14];
            float var8 = this.pageTabsX + (float)var14 * this.pageTabWidth;
            boolean var9 = this.isPageTabHovered(var14, (double)mouseX, (double)mouseY);
            boolean var10 = this.activePage == var15;
            int var11 = !var10 && !var9 ? -8355712 : -1;
            float var12 = 7.2F;
            float var13 = FontRepository.getFont("productsans-medium").getStringWidth(var15.label, 7.2F);
            FontRepository.getFont("productsans-medium")
               .drawString(var15.label, var8 + (this.pageTabWidth - var13) / 2.0F, this.pageTabsY + 13.5F, 7.2F, var11);
         }

         NVGRenderer.globalAlpha(1.0F);
      }
   }

   @Override
   public boolean mouseClicked(double mouseX, double mouseY, int button) {
      if (selectingBind && this.activePage == DropdownClickGUI.ClickPage.MODULE) {
         Click var7 = new Click(mouseX, mouseY, button);
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.mouseClicked(var7.x(), var7.y(), var7.button()));
         return true;
      } else if (button == 0 && this.handlePageTabClick(mouseX, mouseY)) {
         return true;
      } else if (this.activePage == DropdownClickGUI.ClickPage.PARAMS) {
         return this.handleParamsClick(mouseX, mouseY, button);
      } else if (this.activePage == DropdownClickGUI.ClickPage.HUD) {
         if (button == 0 && !this.isHudListHovered(mouseX, mouseY) && this.tryBeginDragHudElement(mouseX, mouseY)) {
            return true;
         } else {
            if (this.hudCategoryPanel != null) {
               this.hudCategoryPanel.mouseClicked(mouseX, mouseY, button);
            }

            return true;
         }
      } else if (this.activePage != DropdownClickGUI.ClickPage.MODULE) {
         return true;
      } else if (button == 0 && this.isSearchHovered(mouseX, mouseY)) {
         this.searchFocused = true;
         return true;
      } else {
         if (button == 0) {
            this.searchFocused = false;
         }

         Click var6 = new Click(mouseX, mouseY, button);
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.mouseClicked(var6.x(), var6.y(), var6.button()));
         return true;
      }
   }

   @Override
   public boolean mouseReleased(double mouseX, double mouseY, int button) {
      if (this.activePage == DropdownClickGUI.ClickPage.HUD) {
         if (button == 0) {
            this.draggingHudModule = null;
         }

         if (this.hudCategoryPanel != null) {
            this.hudCategoryPanel.mouseReleased(mouseX, mouseY, button);
         }

         return true;
      } else if (this.activePage != DropdownClickGUI.ClickPage.MODULE) {
         return true;
      } else {
         Click var6 = new Click(mouseX, mouseY, button);
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.mouseReleased(var6.x(), var6.y(), var6.button()));
         return true;
      }
   }

   @Override
   public boolean mouseScrolled(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) {
      if (this.activePage == DropdownClickGUI.ClickPage.HUD) {
         if (this.hudCategoryPanel != null) {
            this.hudCategoryPanel.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount);
         }

         return true;
      } else if (this.activePage != DropdownClickGUI.ClickPage.MODULE) {
         return true;
      } else {
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount));
         return true;
      }
   }

   @Override
   public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
      if (selectingBind && this.activePage == DropdownClickGUI.ClickPage.MODULE) {
         KeyInput var6 = new KeyInput(keyCode, scanCode, modifiers);
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.keyPressed(var6));
         return true;
      } else if (this.activePage == DropdownClickGUI.ClickPage.PARAMS && this.configInputFocused) {
         if (keyCode == 256 || keyCode == 257 || keyCode == 335) {
            this.configInputFocused = false;
            return true;
         } else if (keyCode == 259) {
            this.configInput = removeLastCodePoint(this.configInput);
            return true;
         } else if (keyCode == 65 && PlayerUtility.isKeyPressed(341)) {
            this.configInput = "";
            return true;
         } else {
            return true;
         }
      } else if (keyCode == 256) {
         if (this.searchFocused) {
            this.searchFocused = false;
            return true;
         } else {
            this.close();
            return true;
         }
      } else if (this.activePage == DropdownClickGUI.ClickPage.HUD) {
         KeyInput var5 = new KeyInput(keyCode, scanCode, modifiers);
         if (this.hudCategoryPanel != null) {
            this.hudCategoryPanel.keyPressed(var5);
         }

         return true;
      } else if (this.activePage != DropdownClickGUI.ClickPage.MODULE) {
         return true;
      } else if (this.handleSearchKey(keyCode)) {
         return true;
      } else {
         KeyInput var4 = new KeyInput(keyCode, scanCode, modifiers);
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.keyPressed(var4));
         return true;
      }
   }

   @Override
   public boolean charTyped(char chr, int modifiers) {
      if (this.activePage == DropdownClickGUI.ClickPage.PARAMS && this.configInputFocused && !Character.isISOControl(chr)) {
         if (this.configInput.length() < 32) {
            this.configInput = this.configInput + chr;
         }

         return true;
      } else if (this.activePage == DropdownClickGUI.ClickPage.HUD) {
         if (this.hudCategoryPanel != null) {
            this.hudCategoryPanel.charTyped(chr, modifiers);
         }

         return true;
      } else if (this.activePage != DropdownClickGUI.ClickPage.MODULE) {
         return true;
      } else if (this.searchFocused && !Character.isISOControl(chr)) {
         this.searchText = this.searchText + chr;
         return true;
      } else {
         CharInput var3 = new CharInput(chr, modifiers);
         this.categoryPanelList.forEach(categoryPanel -> categoryPanel.charTyped((char)var3.codepoint(), var3.modifiers()));
         return true;
      }
   }

   private boolean handleParamsClick(double mouseX, double mouseY, int button) {
      if (button != 0) {
         this.configInputFocused = false;
         return true;
      } else {
         List var6 = this.getConfigNames();
         float var7 = this.pageX + 10.0F;
         float var8 = this.pageY + 28.0F;
         float var9 = 145.0F;
         float var10 = 18.0F;
         float var11 = var7 + 145.0F + 10.0F;
         float var12 = this.pageWidth - (var11 - this.pageX) - 10.0F;
         float var13 = this.pageY + 31.0F;
         float var14 = var13 + 28.0F;

         for (int var15 = 0; var15 < Math.min(var6.size(), 7); var15++) {
            float var16 = var8 + (float)var15 * 18.0F;
            if (this.isHovered(var7, var16, 145.0F, 17.0F, mouseX, mouseY)) {
               this.selectedConfig = (String)var6.get(var15);
               this.configInput = this.selectedConfig;
               this.configInputFocused = false;
               return true;
            }
         }

         if (this.isHovered(var11, var13, var12, 20.0F, mouseX, mouseY)) {
            this.configInputFocused = true;
            return true;
         } else {
            this.configInputFocused = false;
            if (this.isHovered(var11, var14, var12, 18.0F, mouseX, mouseY)) {
               this.saveCurrentConfig(this.configInput);
               return true;
            } else if (this.isHovered(var11, var14 + 23.0F, var12, 18.0F, mouseX, mouseY)) {
               this.loadConfig(this.selectedConfig != null ? this.selectedConfig : this.configInput);
               return true;
            } else if (this.isHovered(var11, var14 + 46.0F, var12, 18.0F, mouseX, mouseY)) {
               this.deleteConfig(this.selectedConfig != null ? this.selectedConfig : this.configInput);
               return true;
            } else {
               return true;
            }
         }
      }
   }

   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);
         return true;
      } else if (keyCode == 65 && PlayerUtility.isKeyPressed(341)) {
         this.searchText = "";
         return true;
      } else {
         return false;
      }
   }

   private boolean isSearchHovered(double mouseX, double mouseY) {
      return mouseX >= (double)this.searchX
         && mouseX <= (double)(this.searchX + this.searchWidth)
         && mouseY >= (double)this.searchY
         && mouseY <= (double)(this.searchY + this.searchHeight);
   }

   private boolean isHudListHovered(double mouseX, double mouseY) {
      return this.hudCategoryPanel != null && this.hudCategoryPanel.isMouseOverPanel(mouseX, mouseY);
   }

   private boolean tryBeginDragHudElement(double mouseX, double mouseY) {
      if (CrucifixBeta.MODULE == null) {
         return false;
      } else {
         ArrayList var5 = CrucifixBeta.MODULE.getModules();

         for (int var6 = var5.size() - 1; var6 >= 0; var6--) {
            dev.crucifixbeta.mod.modules.Module var7 = (dev.crucifixbeta.mod.modules.Module)var5.get(var6);
            if (var7 instanceof HudModule var8 && var7.isOn() && var8.isHudHit((int)mouseX, (int)mouseY)) {
               this.draggingHudModule = var8;
               this.draggingHudOffsetX = (int)mouseX - var8.getHudBoundX();
               this.draggingHudOffsetY = (int)mouseY - var8.getHudBoundY();
               return true;
            }
         }

         return false;
      }
   }

   private void dragHudElements(int mouseX, int mouseY) {
      if (this.draggingHudModule != null) {
         if (Constants.mc.getWindow() != null && GLFW.glfwGetMouseButton(Constants.mc.getWindow().getHandle(), 0) == 1) {
            this.draggingHudModule.setHudPosFromBounds(mouseX - this.draggingHudOffsetX, mouseY - this.draggingHudOffsetY);
         } else {
            this.draggingHudModule = null;
         }
      }
   }

   private void renderHudEditPreviews(DrawContext context) {
      if (CrucifixBeta.MODULE != null) {
         for (dev.crucifixbeta.mod.modules.Module var3 : CrucifixBeta.MODULE.getModules()) {
            if (var3 instanceof HudModule) {
               HudModule var4 = (HudModule)var3;
               if (var3.isOn() && (var4.getHudBoundW() <= 0 || var4.getHudBoundH() <= 0)) {
                  String var5 = var3.getDisplayName();
                  float var6 = var4.getHudSize();
                  float var7 = 7.0F * var6;
                  float var8 = FontRepository.getFont("productsans-medium").getStringWidth(var5, var7);
                  int var9 = Math.max(56, Math.round(FontRepository.getFont("productsans-medium").getStringWidth(var5, 7.0F) + 14.0F));
                  byte var10 = 18;
                  int var11 = var4.getHudRenderX(var9);
                  int var12 = var4.getHudRenderY(18);
                  float var13 = Math.max(1.0F, (float)var9 * var6);
                  float var14 = Math.max(1.0F, 18.0F * var6);
                  NVGRenderer.roundedRect(
                     (float)var11, (float)var12, var13, var14, 5.0F * var6, ColorUtility.scaleOpacity(ColorUtility.getModuleBackgroundColor(), 0.55F)
                  );
                  NVGRenderer.roundedRectOutline(
                     (float)var11,
                     (float)var12,
                     var13,
                     var14,
                     5.0F * var6,
                     1.0F,
                     ColorUtility.applyOpacity((Integer)ColorUtility.getClientTheme().first, 0.45F)
                  );
                  FontRepository.getFont("productsans-medium")
                     .drawString(var5, (float)var11 + 7.0F * var6, (float)var12 + 11.5F * var6, var7, ColorUtility.getEnabledTextColor());
                  var4.setHudEditBounds(var11, var12, Math.round(var13), Math.round(var14));
               }
            }
         }
      }
   }

   private void renderHudHoverOverlay(int mouseX, int mouseY) {
      if (CrucifixBeta.MODULE == null) {
         this.hudHoverAnimations.clear();
      } else {
         boolean var3 = this.isHudListHovered((double)mouseX, (double)mouseY);

         for (dev.crucifixbeta.mod.modules.Module var5 : CrucifixBeta.MODULE.getModules()) {
            if (var5 instanceof HudModule) {
               HudModule var6 = (HudModule)var5;
               if (var5.isOn() && var6.getHudBoundW() > 0 && var6.getHudBoundH() > 0) {
                  boolean var7 = !var3 && var6.isHudHit(mouseX, mouseY);
                  Animation var8 = this.hudHoverAnimations.computeIfAbsent(var6, ignored -> new Animation(Easing.EASE_OUT_SINE, 170L));
                  var8.setDuration(var7 ? 160L : 190L);
                  var8.run(var7 ? 1.0F : 0.0F);
                  float var9 = var8.getValue();
                  if (!(var9 <= 0.01F)) {
                     float var10 = (float)(var6.getHudBoundX() - 3);
                     float var11 = (float)(var6.getHudBoundY() - 3);
                     float var12 = (float)(var6.getHudBoundW() + 6);
                     float var13 = (float)(var6.getHudBoundH() + 6);
                     int var14 = ColorUtility.applyOpacity((Integer)ColorUtility.getClientTheme().first, Math.round(205.0F * var9));
                     int var15 = ColorUtility.applyOpacity((Integer)ColorUtility.getClientTheme().first, Math.round(28.0F * var9));
                     NVGRenderer.roundedRect(var10, var11, var12, var13, 5.0F, var15);
                     NVGRenderer.roundedRectOutline(var10, var11, var12, var13, 5.0F, 1.2F, var14);
                     String var16 = var5.getDisplayName();
                     float var17 = 7.2F;
                     float var18 = FontRepository.getFont("productsans-medium").getStringWidth(var16, 7.2F);
                     float var19 = var18 + 12.0F;
                     float var20 = 17.0F;
                     float var21 = var10 + var12 + 7.0F - (1.0F - var9) * 4.0F;
                     if (var21 + var19 > (float)(Constants.mc.getWindow().getScaledWidth() - 4)) {
                        var21 = var10 - var19 - 7.0F + (1.0F - var9) * 4.0F;
                     }

                     float var22 = var11 + Math.max(0.0F, (var13 - 17.0F) / 2.0F);
                     var22 = Math.max(4.0F, Math.min(var22, (float)Constants.mc.getWindow().getScaledHeight() - 17.0F - 4.0F));
                     NVGRenderer.roundedRect(
                        var21, var22, var19, 17.0F, 5.0F, ColorUtility.applyOpacity(ColorUtility.getPanelBackgroundColor(), Math.round(210.0F * var9))
                     );
                     NVGRenderer.roundedRectOutline(
                        var21,
                        var22,
                        var19,
                        17.0F,
                        5.0F,
                        1.0F,
                        ColorUtility.applyOpacity((Integer)ColorUtility.getClientTheme().first, Math.round(135.0F * var9))
                     );
                     FontRepository.getFont("productsans-medium")
                        .drawString(
                           var16, var21 + 6.0F, var22 + 11.5F, 7.2F, ColorUtility.applyOpacity(ColorUtility.getEnabledTextColor(), Math.round(255.0F * var9))
                        );
                  }
               }
            }
         }

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

         while (var23.hasNext()) {
            Entry var24 = (Entry)var23.next();
            HudModule var25 = (HudModule)var24.getKey();
            if (var25.isOff() || ((Animation)var24.getValue()).getValue() <= 0.001F && ((Animation)var24.getValue()).isFinished()) {
               var23.remove();
            }
         }
      }
   }

   private boolean handlePageTabClick(double mouseX, double mouseY) {
      for (int var5 = 0; var5 < DropdownClickGUI.ClickPage.VALUES.length; var5++) {
         if (this.isPageTabHovered(var5, mouseX, mouseY)) {
            this.activePage = DropdownClickGUI.ClickPage.VALUES[var5];
            this.searchFocused = false;
            return true;
         }
      }

      return false;
   }

   private boolean isPageTabHovered(int index, double mouseX, double mouseY) {
      float var6 = this.pageTabsX + (float)index * this.pageTabWidth;
      return mouseX >= (double)var6
         && mouseX <= (double)(var6 + this.pageTabWidth)
         && mouseY >= (double)this.pageTabsY
         && mouseY <= (double)(this.pageTabsY + this.pageTabsHeight);
   }

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

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

   @Override
   protected void init() {
      this.closing = false;
      this.closeCompleted = false;
      this.activePage = DropdownClickGUI.ClickPage.MODULE;
      displayingBinds = false;
      selectingBind = false;
      typingString = false;
      this.searchFocused = false;
      this.configInputFocused = false;
      this.draggingHudModule = null;
      this.hudHoverAnimations.clear();
      this.pageTabAnimation.setValue((float)this.activePage.ordinal());
      this.pageTabsAnimation.setValue(0.0F);
      this.pageTabsAnimationValue = 0.0F;
      this.searchAnimation.setValue(0.0F);
      this.rebuildCategoryPanels();
      this.rebuildHudCategoryPanel();
      this.categoryPanelList.forEach(CategoryPanel::init);
      if (this.hudCategoryPanel != null) {
         this.hudCategoryPanel.init();
      }
   }

   private void rebuildCategoryPanels() {
      this.categoryPanelList.clear();
      int var1 = 0;

      for (ModuleCategory var5 : ModuleCategory.VALUES) {
         if (var5 != ModuleCategory.DEBUG && var5 != ModuleCategory.HUD && !OpalClient.getInstance().getModuleRepository().getModulesInCategory(var5).isEmpty()
            )
          {
            this.categoryPanelList.add(new CategoryPanel(var5, var1++));
         }
      }

      if (!this.categoryPanelList.isEmpty()) {
         this.categoryPanelList.get(this.categoryPanelList.size() - 1).setLastPanel(true);
      }
   }

   private void rebuildHudCategoryPanel() {
      this.hudCategoryPanel = null;
      if (!OpalClient.getInstance().getModuleRepository().getModulesInCategory(ModuleCategory.HUD).isEmpty()) {
         this.hudCategoryPanel = new CategoryPanel(ModuleCategory.HUD, 0);
         this.hudCategoryPanel.setLastPanel(true);
      }
   }

   @Override
   public void close() {
      if (!selectingBind) {
         if (!this.closing) {
            this.closing = true;
            this.searchFocused = false;
            this.configInputFocused = false;
            typingString = false;
            this.draggingHudModule = null;
            this.hudHoverAnimations.clear();
            ClickGuiBlur.release();
            this.categoryPanelList.forEach(CategoryPanel::close);
            if (this.hudCategoryPanel != null) {
               this.hudCategoryPanel.close();
            }
         }
      }
   }

   private boolean isCloseAnimationComplete() {
      return this.closing && this.pageTabsAnimationValue <= 0.001F && this.pageTabsAnimation.isFinished();
   }

   private void finishClose() {
      if (!this.closeCompleted) {
         this.closeCompleted = true;
         ClickGuiBlur.release();
         if (Constants.mc.currentScreen == this) {
            Constants.mc.setScreen(null);
         }

         if (CrucifixBeta.MODULE != null) {
            dev.crucifixbeta.mod.modules.Module var1 = CrucifixBeta.MODULE.getModuleByName("ClickGui");
            if (var1 != null && var1.isOn()) {
               var1.disable();
            }
         }
      }
   }

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

   static {

      CONFIG_GSON = new GsonBuilder().setPrettyPrinting().create();
   }
@Environment(EnvType.CLIENT)
   private static enum ClickPage {
      MODULE("Module"),
      PARAMS("Params"),
      HUD("HUD");

      private final String label;
      private static final DropdownClickGUI.ClickPage[] VALUES;

      private ClickPage(final String label) {
         this.label = label;
      }

      static {
         VALUES = values();
      }
}
}
