package dev.crucifixbeta.mod.gui.items.buttons;

import dev.crucifixbeta.api.utils.math.Animation;
import dev.crucifixbeta.api.utils.math.Easing;
import dev.crucifixbeta.api.utils.render.Render2DUtil;
import dev.crucifixbeta.mod.gui.clickgui.ClickGuiScreen;
import dev.crucifixbeta.mod.gui.items.Component;
import dev.crucifixbeta.mod.modules.impl.client.ClickGui;
import dev.crucifixbeta.mod.modules.impl.client.ClientSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import java.awt.Color;
import java.util.Locale;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.SelectionManager;
import net.minecraft.util.Formatting;
import org.lwjgl.glfw.GLFW;

@Environment(EnvType.CLIENT)
public class SliderButton extends Button {
   private final double min;
   private final double max;
   private final double difference;
   public final SliderSetting setting;
   public boolean isListening;
   private String currentString = "";
   private boolean drag = false;
   private final Animation valueAnimation = new Animation();

   public SliderButton(SliderSetting setting) {
      super(setting.getName());
      this.setting = setting;
      this.min = setting.getMin();
      this.max = setting.getMax();
      this.difference = this.max - this.min;
      double var2 = this.partialMultiplier();
      this.valueAnimation.from = var2;
      this.valueAnimation.to = var2;
   }

   @Override
   public void drawScreen(DrawContext context, int mouseX, int mouseY, float partialTicks) {
      this.dragSetting(mouseX, mouseY);
      boolean var5 = this.isHovering(mouseX, mouseY);
      this.updateHoverSound(var5);
      Render2DUtil.rect(
         context.getMatrices(), this.x, this.y, this.x + (float)this.width + 7.0F, this.y + (float)this.height - 0.5F, !var5 ? defaultColor : hoverColor
      );
      double var6 = this.getColorDelay();
      double var8 = this.valueAnimation.get(this.partialMultiplier(), ClientSetting.sliderFollowDuration(200L), Easing.CubicInOut);
      float var10 = (float)((double)this.x + (double)((float)this.width + 7.0F) * var8);
      float var11 = (float)this.height - 0.5F;
      int var12 = !var5 ? ClickGui.getInstance().alpha.getValueInt() : ClickGui.getInstance().hoverAlpha.getValueInt();
      if (ClickGui.getInstance().colorMode.getValue() == ClickGui.ColorMode.Spectrum) {
         float var13 = Math.max(0.0F, var10 - this.x);
         Render2DUtil.drawLutRect(
            context.getMatrices(),
            this.x,
            this.y,
            var13,
            var11,
            ClickGui.getInstance().getSpectrumLutId(),
            ClickGui.getInstance().getSpectrumLutHeight(),
            var12
         );
      } else {
         Color var14 = ClickGui.getInstance().getColor(var6);
         Render2DUtil.rect(context.getMatrices(), this.x, this.y, var10, this.y + (float)this.height - 0.5F, var14.getRGB());
      }

      float var15 = this.getCenteredTextY(this.y, (float)this.height - 0.5F);
      if (this.isListening) {
         this.drawString(
            this.currentString + StringButton.getIdleSign(), (double)(this.x + 2.3F), (double)var15, this.getState() ? enableTextColor : defaultTextColor
         );
      } else if (var5 && InputUtil.isKeyPressed(mc.getWindow().getHandle(), 340)) {
         this.drawString("Reset Default", (double)(this.x + 2.3F), (double)var15, enableTextColor);
      } else {
         this.drawSettingString(
            this.setting.getDisplayName() + ":" + Formatting.GRAY + this.formatValue(), (double)(this.x + 2.3F), (double)var15, enableTextColor
         );
      }
   }

   @Override
   public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
      if (mouseButton == 0 && this.isHovering(mouseX, mouseY) && InputUtil.isKeyPressed(mc.getWindow().getHandle(), 340)) {
         this.drag = false;
         this.isListening = false;
         this.currentString = "";
         this.setting.setValue(this.setting.getDefaultValue());
         sound();
      } else {
         if (this.isHovering(mouseX, mouseY)) {
            sound();
            if (mouseButton == 0) {
               if (this.isListening) {
                  this.toggle();
               } else {
                  this.setSettingFromX(mouseX);
                  this.drag = true;
               }
            } else if (mouseButton == 1) {
               this.toggle();
            }
         }
      }
   }

   @Override
   public boolean isHovering(int mouseX, int mouseY) {
      for (Component var4 : ClickGuiScreen.getInstance().getComponents()) {
         if (var4.drag) {
            return false;
         }
      }

      return (float)mouseX >= this.getX()
         && (float)mouseX <= this.getX() + (float)this.getWidth() + 8.0F
         && (float)mouseY >= this.getY()
         && (float)mouseY <= this.getY() + (float)this.height - 1.0F;
   }

   @Override
   public void update() {
      this.setHidden(!this.setting.isVisible());
   }

   @Override
   public void onKeyTyped(char typedChar, int keyCode) {
      if (this.isListening) {
         this.setString(this.currentString + typedChar);
      }
   }

   @Override
   public void onKeyPressed(int key) {
      if (this.isListening) {
         switch (key) {
            case 86:
               if (InputUtil.isKeyPressed(mc.getWindow().getHandle(), 341)) {
                  this.setString(this.currentString + SelectionManager.getClipboard(mc));
               }
               break;
            case 256:
               this.isListening = false;
               break;
            case 257:
            case 335:
               this.enterString();
               break;
            case 259:
               this.setString(StringButton.removeLastChar(this.currentString));
         }
      }
   }

   private void enterString() {
      if (!this.currentString.isEmpty() && this.isNumeric(this.currentString)) {
         this.setting.setValue(Double.parseDouble(this.currentString));
      } else {
         this.setting.setValue(this.setting.getDefaultValue());
      }

      this.onMouseClick();
   }

   public void setString(String newString) {
      this.currentString = newString;
   }

   private void dragSetting(int mouseX, int mouseY) {
      if (this.drag && this.isHovering(mouseX, mouseY) && GLFW.glfwGetMouseButton(mc.getWindow().getHandle(), 0) == 1) {
         this.setSettingFromX(mouseX);
      } else {
         this.drag = false;
      }
   }

   @Override
   public void toggle() {
      this.setString(this.setting.getValueFloat() + "");
      this.isListening = !this.isListening;
   }

   @Override
   public boolean getState() {
      return !this.isListening;
   }

   private void setSettingFromX(int mouseX) {
      double var2 = (double)((float)mouseX - this.x) / ((double)this.width + 7.4);
      double var4 = this.setting.getMin() + this.difference * var2;
      var4 = Math.max(this.min, Math.min(var4, this.max));
      this.setting.setValue(var4);
   }

   private double part() {
      return this.setting.getValue() - this.min;
   }

   private double partialMultiplier() {
      return Math.max(0.0, Math.min(this.part() / this.difference, 1.0));
   }

   private String formatValue() {
      double var1 = this.setting.getValue();
      String var3;
      if (var1 == (double)((int)var1)) {
         var3 = String.valueOf((int)var1);
      } else {
         var3 = String.format(Locale.ROOT, "%.3f", var1)
            .replaceAll("0+$", "")
            .replaceAll("\\.$", "");
      }

      return var3 + this.setting.getSuffix();
   }

   public void resetFillAnimation() {
      this.valueAnimation.from = 0.0;
      this.valueAnimation.to = 0.0;
   }

   private boolean isNumeric(String str) {
      return str.matches("-?\\d+(\\.\\d+)?");
   }
}
