package dev.crucifixbeta.mod.modules;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.ResizeEvent;
import dev.crucifixbeta.api.utils.render.Render2DUtil;
import dev.crucifixbeta.mod.modules.settings.impl.BooleanSetting;
import dev.crucifixbeta.mod.modules.settings.impl.ColorSetting;
import dev.crucifixbeta.mod.modules.settings.impl.EnumSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import java.awt.Color;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;

@Environment(EnvType.CLIENT)
public abstract class HudModule extends Module {
   private static int cachedScaledWidth;
   private static int cachedScaledHeight;
   public final EnumSetting<HudModule.Corner> corner;
   public final SliderSetting hudSize;
   public final BooleanSetting background;
   public final ColorSetting backgroundColor;
   public final SliderSetting backgroundRadius;
   public final BooleanSetting backgroundBlur;
   public final SliderSetting blurStrength;
   protected final SliderSetting x;
   protected final SliderSetting y;
   private int lastHudX;
   private int lastHudY;
   private int lastHudW;
   private int lastHudH;
   private boolean scaledRenderActive;

   public HudModule(String name, String chinese, int defaultX, int defaultY) {
      this(name, "", chinese, defaultX, defaultY, HudModule.Corner.LeftTop);
   }

   public HudModule(String name, String description, String chinese, int defaultX, int defaultY) {
      this(name, description, chinese, defaultX, defaultY, HudModule.Corner.LeftTop);
   }

   protected HudModule(String name, String description, String chinese, int defaultX, int defaultY, HudModule.Corner defaultCorner) {
      super(name, description, defaultCategory(name));
      this.setChinese(chinese);
      this.corner = new EnumSetting<>("Corner", defaultCorner);
      this.hudSize = this.add(new SliderSetting("HudSize", 1.0, 0.5, 3.0, 0.05));
      this.background = this.add(new BooleanSetting("Background", false).setParent());
      this.backgroundColor = this.add(new ColorSetting("BackgroundColor", new Color(0, 0, 0, 110), this.background::isOpen));
      this.backgroundRadius = this.add(new SliderSetting("BackgroundRadius", 4.0, 0.0, 20.0, 0.5, this.background::isOpen));
      this.backgroundBlur = this.add(new BooleanSetting("BackgroundBlur", false).setParent());
      this.blurStrength = this.add(new SliderSetting("BlurStrength", 12.0, 1.0, 60.0, 1.0, this.backgroundBlur::isOpen));
      this.x = this.add(new SliderSetting("X", defaultX, 0, 1500));
      this.y = this.add(new SliderSetting("Y", defaultY, 0, 1000));
   }

   private static Module.Category defaultCategory(String name) {
      return switch (name) {
         case "Armor", "ArrayList", "EffectHud", "Info", "Items", "WaterMark", "GUICharacter", "PlayerModule", "TextRadar", "PotionHud", "InventoryHud", "PlayerListHud", "TargetInfo", "Clock", "Compass", "KeyBinds", "KeyStrokes", "Radar", "Health" -> Module.Category.HUD;
         default -> Module.Category.Client;
      };
   }

   public static void updateWindowSize() {
      if (mc != null && mc.getWindow() != null) {
         cachedScaledWidth = mc.getWindow().getScaledWidth();
         cachedScaledHeight = mc.getWindow().getScaledHeight();
      }
   }

   private static int getScaledWidth() {
      if (cachedScaledWidth <= 0 && mc != null && mc.getWindow() != null) {
         cachedScaledWidth = mc.getWindow().getScaledWidth();
      }

      return cachedScaledWidth;
   }

   private static int getScaledHeight() {
      if (cachedScaledHeight <= 0 && mc != null && mc.getWindow() != null) {
         cachedScaledHeight = mc.getWindow().getScaledHeight();
      }

      return cachedScaledHeight;
   }

   @EventListener
   public void onResize(ResizeEvent event) {
      updateWindowSize();
   }

   public final int getHudX() {
      return this.x.getValueInt();
   }

   public final int getHudY() {
      return this.y.getValueInt();
   }

   public final float getHudSize() {
      return Math.max(0.05F, this.hudSize.getValueFloat());
   }

   public final void setHudX(int x) {
      this.x.setValue(clamp((double)x, this.x.getMin(), this.x.getMax()));
   }

   public final void setHudY(int y) {
      this.y.setValue(clamp((double)y, this.y.getMin(), this.y.getMax()));
   }

   public final void setHudPos(int x, int y) {
      this.setHudX(x);
      this.setHudY(y);
   }

   public final void beginScaledRender(DrawContext context) {
      float var2 = this.getHudSize();
      this.scaledRenderActive = true;
      context.getMatrices().push();
      context.getMatrices().scale(var2, var2, 1.0F);
   }

   public final void endScaledRender(DrawContext context) {
      context.getMatrices().pop();
      this.scaledRenderActive = false;
   }

   public final void renderBackground(DrawContext context) {
      if (this.lastHudW > 0 && this.lastHudH > 0) {
         if (this.background.getValue() || this.backgroundBlur.getValue()) {
            float var2 = 2.0F;
            float var3 = (float)this.lastHudX - var2;
            float var4 = (float)this.lastHudY - var2;
            float var5 = (float)this.lastHudW + var2 * 2.0F;
            float var6 = (float)this.lastHudH + var2 * 2.0F;
            if (this.backgroundBlur.getValue() && CrucifixBeta.BLUR != null) {
               CrucifixBeta.BLUR.applyBlur(this.blurStrength.getValueFloat(), var3, var4, var5, var6);
            }

            if (this.background.getValue()) {
               Render2DUtil.drawRoundedRect(
                  context.getMatrices(), var3, var4, var5, var6, this.backgroundRadius.getValueFloat(), this.backgroundColor.getValue()
               );
            }
         }
      }
   }

   public final int getHudRenderX(int elementW) {
      int var2 = getScaledWidth();
      if (var2 <= 0) {
         return this.getHudX();
      } else {
         float var3 = this.getHudSize();
         int var4 = Math.max(0, (int)Math.ceil((double)elementW * (double)var3));
         int var5 = this.getHudX();
         int var6 = this.corner.getValue().isRight() ? var2 - var4 - var5 : var5;
         var6 = clampInt(var6, 0, Math.max(0, var2 - var4));
         return this.scaledRenderActive ? (int)Math.floor((double)var6 / (double)var3) : var6;
      }
   }

   public final int getHudRenderY(int elementH) {
      int var2 = getScaledHeight();
      if (var2 <= 0) {
         return this.getHudY();
      } else {
         float var3 = this.getHudSize();
         int var4 = Math.max(0, (int)Math.ceil((double)elementH * (double)var3));
         int var5 = this.getHudY();
         int var6 = this.corner.getValue().isBottom() ? var2 - var4 - var5 : var5;
         var6 = clampInt(var6, 0, Math.max(0, var2 - var4));
         return this.scaledRenderActive ? (int)Math.floor((double)var6 / (double)var3) : var6;
      }
   }

   public final void setHudPosFromBounds(int boundsX, int boundsY) {
      int var3 = getScaledWidth();
      int var4 = getScaledHeight();
      if (var3 > 0 && var4 > 0) {
         int var5 = Math.max(0, this.getHudBoundW());
         int var6 = Math.max(0, this.getHudBoundH());
         HudModule.Corner var7 = this.corner.getValue();
         int var8 = var7.isRight() ? var3 - var5 - boundsX : boundsX;
         int var9 = var7.isBottom() ? var4 - var6 - boundsY : boundsY;
         this.setHudPos(var8, var9);
      } else {
         this.setHudPos(boundsX, boundsY);
      }
   }

   private static int clampInt(int v, int min, int max) {
      return v < min ? min : Math.min(v, max);
   }

   private static double clamp(double v, double min, double max) {
      return v < min ? min : Math.min(v, max);
   }

   protected final void setHudBounds(int x, int y, int w, int h) {
      float var5 = this.scaledRenderActive ? this.getHudSize() : 1.0F;
      this.lastHudX = Math.round((float)x * var5);
      this.lastHudY = Math.round((float)y * var5);
      this.lastHudW = Math.max(1, (int)Math.ceil((double)Math.max(0, w) * (double)var5));
      this.lastHudH = Math.max(1, (int)Math.ceil((double)Math.max(0, h) * (double)var5));
   }

   public final void setHudEditBounds(int x, int y, int w, int h) {
      this.setHudBounds(x, y, w, h);
   }

   protected final void clearHudBounds() {
      this.lastHudW = this.lastHudH = 0;
   }

   public final int getHudBoundX() {
      return this.lastHudX;
   }

   public final int getHudBoundY() {
      return this.lastHudY;
   }

   public final int getHudBoundW() {
      return this.lastHudW;
   }

   public final int getHudBoundH() {
      return this.lastHudH;
   }

   public final boolean isHudHit(int mouseX, int mouseY) {
      return this.lastHudW > 0
         && this.lastHudH > 0
         && mouseX >= this.lastHudX
         && mouseX <= this.lastHudX + this.lastHudW
         && mouseY >= this.lastHudY
         && mouseY <= this.lastHudY + this.lastHudH;
   }

   public final boolean isHudOverlapping(int x1, int y1, int x2, int y2) {
      if (this.lastHudW > 0 && this.lastHudH > 0) {
         int var5 = Math.min(x1, x2);
         int var6 = Math.min(y1, y2);
         int var7 = Math.max(x1, x2);
         int var8 = Math.max(y1, y2);
         int var9 = this.lastHudX;
         int var10 = this.lastHudY;
         int var11 = this.lastHudX + this.lastHudW;
         int var12 = this.lastHudY + this.lastHudH;
         return var5 < var11 && var7 > var9 && var6 < var12 && var8 > var10;
      } else {
         return false;
      }
   }

   static {

      cachedScaledWidth = -1;
      cachedScaledHeight = -1;
   }
@Environment(EnvType.CLIENT)
   public static enum Corner {
      LeftTop(false, false),
      RightTop(true, false),
      LeftBottom(false, true),
      RightBottom(true, true);

      private final boolean right;
      private final boolean bottom;

      private Corner(boolean right, boolean bottom) {
         this.right = right;
         this.bottom = bottom;
      }

      public boolean isRight() {
         return this.right;
      }

      public boolean isBottom() {
         return this.bottom;
      }

}
}
