package dev.crucifixbeta.mod.gui.items;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.utils.i18n.LangUtil;
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.core.impl.FontManager;
import dev.crucifixbeta.mod.Mod;
import dev.crucifixbeta.mod.gui.clickgui.ClickGuiScreen;
import dev.crucifixbeta.mod.gui.items.buttons.Button;
import dev.crucifixbeta.mod.gui.items.buttons.ModuleButton;
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.render.AntiAlias;
import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.DrawContext;

@Environment(EnvType.CLIENT)
public class Component extends Mod {
   private final List<ModuleButton> items = new ArrayList<>();
   private final Module.Category category;
   public boolean drag;
   protected DrawContext context;
   private int x;
   private int y;
   private float animX;
   private float animY;
   private float mouseMoveOffsetX;
   private float mouseMoveOffsetY;
   private float pageOffsetX;
   private final Animation xAnimation = new Animation();
   private final Animation yAnimation = new Animation();
   private final Animation openAnimation = new Animation();
   private int x2;
   private int y2;
   private int width;
   private int height;
   private boolean open;
   private boolean hidden = false;
   private int openAnimIndex;
   private boolean entranceAnimation = true;
   private float listScrollOffset;

   public Component(String name, Module.Category category, int x, int y, boolean open) {
      super(name);
      this.category = category;
      this.setX(x);
      this.setY(y);
      this.animX = (float)this.x;
      this.animY = (float)this.y;
      if (ClickGui.getInstance() != null) {
         this.setWidth(ClickGui.getInstance().moduleButtonWidth.getValueInt());
         this.setHeight(ClickGui.getInstance().categoryBarHeight.getValueInt() + 5);
      } else {
         this.setWidth(93);
         this.setHeight(18);
      }

      this.open = open;
      this.setupItems();
   }

   public void setupItems() {
   }

   private void drag(int mouseX, int mouseY) {
      if (this.drag) {
         this.x = this.x2 + mouseX;
         this.y = this.y2 + mouseY;
         this.animX = (float)this.x;
         this.animY = (float)this.y;
      }
   }

   private void updatePosition() {
      if (ClickGui.getInstance().scrollAnim.getValue() && !this.drag) {
         int var1 = Math.max(1, ClickGui.getInstance().scrollAnimLength.getValueInt());
         Easing var2 = ClickGui.getInstance().scrollAnimEasing.getValue();
         this.animX = (float)this.xAnimation.get((double)this.x, (long)var1, var2);
         this.animY = (float)this.yAnimation.get((double)this.y, (long)var1, var2);
      } else {
         this.animX = (float)this.x;
         this.animY = (float)this.y;
         this.xAnimation.from = (double)this.x;
         this.xAnimation.to = (double)this.x;
         this.yAnimation.from = (double)this.y;
         this.yAnimation.to = (double)this.y;
      }
   }

   protected double getColorDelay() {
      return (double)this.getY() / 10.0;
   }

   public void drawScreen(DrawContext context, int mouseX, int mouseY, float partialTicks) {
      this.context = context;
      this.drag(mouseX, mouseY);
      this.updatePosition();
      int var5 = this.getX();
      int var6 = this.getY();
      float var7 = this.getTotalItemHeight() - 2.0F;
      long var8 = 200L;
      Easing var10 = Easing.CubicInOut;
      ClientSetting var11 = ClientSetting.INSTANCE;
      if (var11 != null && var11.clickGuiAnim.getValue()) {
         var8 = Math.max(50L, (long)var11.clickGuiAnimTime.getValueInt()) + (this.entranceAnimation ? (long)this.openAnimIndex * 65L : 0L);
         var10 = var11.clickGuiAnimEase.getValue();
      }

      double var12 = this.openAnimation.get(this.open ? 1.0 : 0.0, var8, var10);
      if (this.entranceAnimation && var12 > 0.995) {
         this.entranceAnimation = false;
      }

      float var14 = (float)((double)var7 * var12);
      float var15 = (float)var5;
      float var16 = (float)var6;
      float var17 = (float)this.width;
      float var18 = (float)this.height - 5.0F;
      double var19 = this.getColorDelay();
      int var21 = ClickGui.getInstance().topAlpha.getValueInt();
      float var22 = var11 != null ? var11.cornerRadius.getValueFloat() : 0.0F;
      ColorsModule var23 = ColorsModule.INSTANCE;
      boolean var24 = var23 != null && var23.colorMode.getValue() == ColorsModule.ColorMode.Static;
      Color var25 = var23 != null ? var23.headerBg.getValue() : ClickGui.getInstance().getColor(var19);
      float var26 = this.getVisibleBodyHeight(var14);
      this.clampListScroll(var7, var26);
      float var27 = var18 + Math.max(0.0F, var26);
      this.drawGlassColumn(context, var15, var16, var17, var27, Math.max(6.0F, var22), var11);
      int var28 = var24 ? var25.getAlpha() : Math.min(var21, 178);
      Render2DUtil.drawRoundedRect(context.getMatrices(), var15, var16, var17, var18, var22, ColorUtil.injectAlpha(var25, var28));
      if (var11 != null && var11.panelBorder.getValue()) {
         Render2DUtil.drawRoundedStroke(
            context.getMatrices(), var15, var16, var17, var18, var22, new Color(ClickGui.getInstance().hoverColor.getValue().getRGB()), 32
         );
      }

      float var29 = (float)var6 + (float)this.height - 5.0F;
      if (var12 > 0.01) {
         float var30 = (float)var5;
         float var31 = (float)this.width;
         Color var33 = var23 != null ? var23.panelBg.getValue() : ClickGui.getInstance().backGround.getValue();
         if (var33.getAlpha() > 0 || ClickGui.getInstance().backGround.booleanValue) {
            int var34 = var24 ? var33.getAlpha() : Math.min(var33.getAlpha(), 112);
            Render2DUtil.drawRect(context.getMatrices(), var30, var29, var31, var26, ColorUtil.injectAlpha(var33, var34));
            if (var11 != null && var11.panelBorder.getValue()) {
               Render2DUtil.drawRectWithOutline(
                  context.getMatrices(), var30, var29, var31, var26, new Color(0, 0, 0, 0), new Color(ClickGui.getInstance().hoverColor.getValue().getRGB())
               );
            }
         }

         if (var11 != null && var11.panelBorder.getValue() && !ClickGui.getInstance().backGround.booleanValue) {
            Render2DUtil.drawRectWithOutline(
               context.getMatrices(), var30, var29, var31, var26, new Color(0, 0, 0, 0), new Color(ClickGui.getInstance().hoverColor.getValue().getRGB())
            );
         }

         if (ClickGui.getInstance().line.getValue()) {
            float var50 = (float)var6 + (float)this.height - 5.0F;
            float var35 = var29 + var26;
            double var36 = 0.25;
            float var38 = (float)var5 + 0.2F;
            float var39 = (float)(var5 + this.width);
            int var40 = ClickGui.getInstance().topAlpha.getValueInt();
            if (ClickGui.getInstance().colorMode.getValue() == ClickGui.ColorMode.Spectrum) {
               float var41 = 1.0F;
               Render2DUtil.drawLutRect(
                  context.getMatrices(),
                  var38,
                  var50,
                  var41,
                  var35 - var50,
                  ClickGui.getInstance().getSpectrumLutId(),
                  ClickGui.getInstance().getSpectrumLutHeight(),
                  var40
               );
               Render2DUtil.drawLutRect(
                  context.getMatrices(),
                  var39 - var41,
                  var50,
                  var41,
                  var35 - var50,
                  ClickGui.getInstance().getSpectrumLutId(),
                  ClickGui.getInstance().getSpectrumLutHeight(),
                  var40
               );
            } else {
               Color var56 = ClickGui.getInstance().getColor((double)var50 * var36);
               Color var42 = ClickGui.getInstance().getColor((double)var35 * var36);
               int var43 = var24 ? var56.getRGB() : ColorUtil.injectAlpha(var56.getRGB(), var40);
               int var44 = var24 ? var42.getRGB() : ColorUtil.injectAlpha(var42.getRGB(), var40);
               Render2DUtil.verticalGradient(context.getMatrices(), var38, var50, var38 + 1.0F, var35, var43, var44);
               Render2DUtil.verticalGradient(context.getMatrices(), var39 - 1.0F, var50, var39, var35, var43, var44);
            }

            Color var57 = ClickGui.getInstance().getColor((double)var35 * var36);
            int var59 = var24 ? var57.getRGB() : ColorUtil.injectAlpha(var57.getRGB(), var40);
            Render2DUtil.drawLine(context.getMatrices(), (float)var5, var35, (float)(var5 + this.width), var35, var59);
         }
      }

      String var47 = LangUtil.category(this.category);
      float var48 = FontManager.shouldUseClientFont(var47, FontManager.isCustomFontEnabled()) ? FontManager.ui.getFontHeight() : 9.0F;
      float var32 = var16 + (var18 - var48) / 2.0F + (float)ClickGui.getInstance().titleOffset.getValueInt();
      this.drawString(var47, (double)(var15 + 5.0F), (double)var32, Button.enableTextColor);
      float var49 = var16 + (var18 - FontManager.icon.getFontHeight()) / 2.0F;
      FontManager.icon.drawString(context.getMatrices(), this.category.getIcon(), (double)(var15 + var17 - 15.5F), (double)var49, Button.enableTextColor);
      if (var12 > 0.01) {
         int var51 = var5 - 1;
         int var52 = (int)((float)var6 + (float)this.height - 6.0F);
         int var45 = var5 + this.width + 1;
         int var46 = (int)Math.round((double)var29 + (double)var26) + 1;
         context.enableScissor(var51, var52, var45, var46);
         float var53 = (float)(this.getY() + this.getHeight()) - 3.0F - this.listScrollOffset;

         for (ModuleButton var55 : this.getItems()) {
            if (!var55.isHidden()) {
               var55.setLocation((float)var5 + 2.0F, var53);
               var55.setWidth(this.getWidth() - 4);
               if (!(var55.itemHeight > 0.0) && !var55.subOpen) {
                  var55.drawScreen(context, mouseX, mouseY, partialTicks);
               } else {
                  int var58 = (int)var55.x - 1;
                  int var60 = (int)var55.y - 1;
                  int var61 = (int)(var55.x + (float)var55.getWidth() + 1.0F);
                  int var62 = (int)((double)(var53 + (float)var55.getButtonHeight() + 1.5F) + var55.itemHeight) + 1;
                  context.enableScissor(var58, var60, var61, var62);
                  var55.drawScreen(context, mouseX, mouseY, partialTicks);
                  context.disableScissor();
               }

               var53 += (float)var55.getButtonHeight() + 1.5F + (float)var55.itemHeight;
            }
         }

         context.disableScissor();
      }
   }

   private float getVisibleBodyHeight(float totalItemHeight) {
      if (mc != null && mc.getWindow() != null) {
         float var2 = (float)this.getY() + (float)this.getHeight() - 5.0F;
         float var3 = (float)mc.getWindow().getScaledHeight() - 8.0F;
         float var4 = Math.max(0.0F, var3 - var2);
         return Math.max(0.0F, Math.min(totalItemHeight, var4));
      } else {
         return Math.max(0.0F, totalItemHeight);
      }
   }

   private void clampListScroll(float totalItemHeight, float bodyVisibleHeight) {
      float var3 = Math.max(0.0F, totalItemHeight - bodyVisibleHeight);
      if (this.listScrollOffset < 0.0F) {
         this.listScrollOffset = 0.0F;
      }

      if (this.listScrollOffset > var3) {
         this.listScrollOffset = var3;
      }
   }

   private void drawGlassColumn(DrawContext context, float x, float y, float width, float height, float radius, ClientSetting cs) {
      if (!(width <= 0.0F) && !(height <= 0.0F)) {
         boolean var8 = cs != null && cs.guiGlass.getValue();
         if (var8) {
            float var9 = cs != null ? cs.guiGlassBlur.getValueFloat() : 38.0F;
            float var10 = (float)ClickGui.getInstance().blurType.getValue().ordinal();
            CrucifixBeta.BLUR.applyBlur(var9, x, y, width, height, var10);
            Color var11 = ColorsModule.INSTANCE != null ? ColorsModule.INSTANCE.panelBg.getValue() : ClickGui.getInstance().backGround.getValue();
            Color var12 = ClickGui.getInstance().getActiveColor((double)y * 0.25);
            boolean var13 = ColorsModule.INSTANCE != null && ColorsModule.INSTANCE.colorMode.getValue() == ColorsModule.ColorMode.Static;
            int var14 = var13 ? var11.getAlpha() : Math.min(var11.getAlpha(), 112);
            Render2DUtil.drawRoundedRectForcedAA(
               context.getMatrices(), x, y, width, height, radius, new Color(var11.getRed(), var11.getGreen(), var11.getBlue(), var14)
            );
            Render2DUtil.drawRoundedRectForcedAA(
               context.getMatrices(),
               x + 1.0F,
               y + 1.0F,
               width - 2.0F,
               Math.min(18.0F, height - 2.0F),
               Math.max(0.0F, radius - 1.0F),
               new Color(255, 255, 255, 8)
            );
            Render2DUtil.drawRoundedStroke(context.getMatrices(), x, y, width, height, radius, new Color(255, 255, 255, 24), 18);
            Render2DUtil.drawRoundedStroke(
               context.getMatrices(), x + 0.6F, y + 0.6F, width - 1.2F, height - 1.2F, Math.max(0.0F, radius - 1.0F), ColorUtil.injectAlpha(var12, 24), 18
            );
         }
      }
   }

   public void mouseClicked(int mouseX, int mouseY, int mouseButton) {
      if (mouseButton == 0 && this.isHovering(mouseX, mouseY)) {
         if (ClickGui.getInstance().mouseMove.getValue()) {
            this.setX(this.getX());
            this.setY(this.getY());
            this.animX = (float)this.x;
            this.animY = (float)this.y;
            this.xAnimation.from = (double)this.x;
            this.xAnimation.to = (double)this.x;
            this.yAnimation.from = (double)this.y;
            this.yAnimation.to = (double)this.y;
         }

         this.x2 = this.getX() - mouseX;
         this.y2 = this.getY() - mouseY;
         ClickGuiScreen.getInstance().getComponents().forEach(component -> {
            if (component.drag) {
               component.drag = false;
            }
         });
         this.drag = true;
      } else if (mouseButton == 1 && this.isHovering(mouseX, mouseY)) {
         this.open = !this.open;
         Item.sound();
      } else if (this.open) {
         if (this.isListMouseOver(mouseX, mouseY)) {
            this.getItems().forEach(item -> {
               if (!item.isHidden() && item.getVisibleHeight() > 0.01 && this.isItemVisibleInPanel(item)) {
                  item.mouseClicked(mouseX, mouseY, mouseButton);
               }
            });
         }
      }
   }

   public void mouseReleased(int mouseX, int mouseY, int releaseButton) {
      if (releaseButton == 0) {
         this.drag = false;
      }

      if (this.open) {
         this.getItems().forEach(item -> {
            if (!item.isHidden() && item.getVisibleHeight() > 0.01 && this.isItemVisibleInPanel(item)) {
               item.mouseReleased(mouseX, mouseY, releaseButton);
            }
         });
      }
   }

   public void onKeyTyped(char typedChar, int keyCode) {
      if (this.open) {
         this.getItems().forEach(item -> item.onKeyTyped(typedChar, keyCode));
      }
   }

   public void onKeyPressed(int key) {
      if (this.open) {
         this.getItems().forEach(item -> item.onKeyPressed(key));
      }
   }

   public void addButton(ModuleButton button) {
      this.items.add(button);
   }

   public void scrollList(double verticalAmount) {
      if (this.open) {
         float var3 = Math.max(0.0F, this.getTotalItemHeight() - 2.0F);
         float var4 = this.getVisibleBodyHeight(var3);
         float var5 = Math.max(0.0F, var3 - var4);
         if (var5 <= 0.0F) {
            this.listScrollOffset = 0.0F;
         } else {
            this.listScrollOffset += verticalAmount < 0.0 ? 15.0F : -15.0F;
            this.listScrollOffset = Math.max(0.0F, Math.min(var5, this.listScrollOffset));
         }
      }
   }

   public boolean isListMouseOver(int mouseX, int mouseY) {
      if (!this.open) {
         return false;
      } else {
         float var3 = (float)this.getY() + (float)this.getHeight() - 5.0F;
         float var4 = this.getVisibleBodyHeight(Math.max(0.0F, this.getTotalItemHeight() - 2.0F));
         return mouseX >= this.getX() && mouseX <= this.getX() + this.getWidth() && (float)mouseY >= var3 && (float)mouseY <= var3 + var4;
      }
   }

   private boolean isItemVisibleInPanel(Item item) {
      float var2 = (float)this.getY() + (float)this.getHeight() - 5.0F;
      float var3 = var2 + this.getVisibleBodyHeight(Math.max(0.0F, this.getTotalItemHeight() - 2.0F));
      return item.getY() + (float)item.getHeight() >= var2 && item.getY() <= var3;
   }

   public int getX() {
      return (int)(this.animX + this.mouseMoveOffsetX + this.pageOffsetX);
   }

   public int getTargetX() {
      return this.x;
   }

   public void setX(int x) {
      this.x = x;
   }

   public int getY() {
      return (int)(this.animY + this.mouseMoveOffsetY);
   }

   public int getTargetY() {
      return this.y;
   }

   public void setY(int y) {
      this.y = y;
   }

   public int getWidth() {
      return this.width;
   }

   public void setWidth(int width) {
      this.width = width;
   }

   public int getHeight() {
      return this.height;
   }

   public void setHeight(int height) {
      this.height = height;
   }

   public boolean isHidden() {
      return this.hidden;
   }

   public void setHidden(boolean hidden) {
      this.hidden = hidden;
   }

   public boolean isOpen() {
      return this.open;
   }

   public final List<ModuleButton> getItems() {
      return this.items;
   }

   public Module.Category getCategory() {
      return this.category;
   }

   public void setMouseMoveOffset(float x, float y) {
      this.mouseMoveOffsetX = x;
      this.mouseMoveOffsetY = y;
   }

   public void setPageOffsetX(float x) {
      this.pageOffsetX = x;
   }

   public void setOpenAnimationIndex(int index) {
      this.openAnimIndex = Math.max(0, index);
      this.entranceAnimation = true;
   }

   public boolean isHovering(int mouseX, int mouseY) {
      int var3 = ClickGui.getInstance().categoryWidth.getValueInt();
      int var4 = Math.round((float)this.getX() + ((float)this.getWidth() - (float)var3) / 2.0F);
      int var5 = this.getY();
      int var7 = this.getHeight() - 5;
      return mouseX >= var4 && mouseX <= var4 + var3 && mouseY >= var5 && mouseY <= var5 + var7;
   }

   public boolean isMouseOver(int mouseX, int mouseY) {
      if (this.isHovering(mouseX, mouseY)) {
         return true;
      } else if (!this.open) {
         return false;
      } else {
         float var3 = this.getTotalItemHeight() - 2.0F;
         int var4 = this.getY() + this.getHeight() - 5;
         return mouseX >= this.getX()
            && mouseX <= this.getX() + this.getWidth()
            && (float)mouseY >= (float)var4
            && (float)mouseY <= (float)var4 + this.getVisibleBodyHeight(var3);
      }
   }

   private float getTotalItemHeight() {
      float var1 = 0.0F;

      for (ModuleButton var3 : this.getItems()) {
         var3.update();
         if (var3.isHidden()) {
            var3.itemHeight = 0.0;
         } else {
            double var4 = var3.animation.get(var3.subOpen ? 1.0 : 0.0, 200L, Easing.CubicInOut);
            var3.itemHeight = var3.getVisibleItemHeight() * var4;
            var1 += (float)var3.getButtonHeight() + 1.5F + (float)var3.itemHeight;
         }
      }

      return var1;
   }

   protected void drawString(String text, double x, double y, Color color) {
      this.drawString(text, x, y, color.hashCode());
   }

   protected void drawString(String text, double x, double y, int color) {
      boolean var7 = FontManager.isShadowEnabled();
      AntiAlias.withTextRender(() -> {
         if (FontManager.shouldUseClientFont(text, FontManager.isCustomFontEnabled())) {
            FontManager.ui.drawString(this.context.getMatrices(), text, (double)((int)x), (double)((int)y), color, var7);
         } else {
            AntiAlias.drawText(this.context, mc.textRenderer, text, (int)x, (int)y, color, var7);
         }
      });
   }
}
