package wtf.opal.client.screen.click.dropdown.panel.property.impl;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.font.TextHandler;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.input.KeyInput;
import net.minecraft.client.util.SelectionManager.SelectionType;
import net.minecraft.util.StringHelper;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import wtf.opal.client.Constants;
import wtf.opal.client.feature.module.property.impl.StringProperty;
import wtf.opal.client.renderer.NVGRenderer;
import wtf.opal.client.renderer.repository.FontRepository;
import wtf.opal.client.renderer.text.NVGTextRenderer;
import wtf.opal.client.screen.click.dropdown.DropdownClickGUI;
import wtf.opal.client.screen.click.dropdown.panel.property.PropertyPanel;
import wtf.opal.utility.misc.HoverUtility;
import wtf.opal.utility.render.ColorUtility;

@Environment(EnvType.CLIENT)
public final class StringPropertyComponent extends PropertyPanel<StringProperty> {
   private boolean focused;
   private int selectionStart;
   private int selectionEnd;

   public StringPropertyComponent(StringProperty property) {
      super(property);
   }

   @Override
   public void render(DrawContext context, int mouseX, int mouseY, float delta) {
      this.setHeight(26.0F);
      super.render(context, mouseX, mouseY, delta);
      StringProperty var5 = this.getProperty();
      NVGTextRenderer var6 = FontRepository.getFont("productsans-medium");
      var6.drawString(var5.getName(), this.x + 5.0F, this.y + 8.5F, 7.0F, -1);
      NVGRenderer.roundedRectOutline(this.x + 5.0F, this.y + 13.0F, this.width - 10.0F, 10.0F, 2.5F, 1.5F, -11513776);
      NVGRenderer.roundedRect(
         this.x + 5.0F, this.y + 13.0F, this.width - 10.0F, 10.0F, 2.5F, ColorUtility.scaleOpacity(ColorUtility.getModuleBackgroundColor(), 0.86F)
      );
      if (!var5.getValue().isEmpty()) {
         String var7 = this.getSelectedText(var5.getValue());
         if (!var7.isEmpty() && this.focused) {
            NVGRenderer.rect(this.x + 7.0F, this.y + 20.0F - 5.5F, var6.getStringWidth(var7, 7.0F), 7.0F, -14396782);
         }

         var6.drawString(var5.getValue(), this.x + 7.0F, this.y + 20.0F, 7.0F, -8355712);
         if (this.focused && var7.isEmpty() && Constants.mc.player.age % 20 > 8) {
            NVGRenderer.rect(
               this.x + 7.5F + var6.getStringWidth(var5.getValue().substring(0, this.selectionStart), 7.0F), this.y + 20.0F - 5.5F, 0.5F, 7.0F, -1
            );
         }
      }
   }

   @Override
   public void init() {
      this.focused = false;
      DropdownClickGUI.typingString = false;
   }

   @Override
   public void mouseClicked(double mouseX, double mouseY, int button) {
      this.focused = button == 0 && HoverUtility.isHovering(this.x, this.y, this.width, this.height, mouseX, mouseY);
      DropdownClickGUI.typingString = this.focused;
      if (this.focused) {
         double var6 = mouseX - (double)(this.x + 7.0F);
         float var8 = 0.0F;

         int var9;
         for (var9 = 0; var9 < this.getProperty().getValue().length(); var9++) {
            NVGTextRenderer var10 = FontRepository.getFont("productsans-medium");
            float var11 = var10.getStringWidth(String.valueOf(this.getProperty().getValue().charAt(var9)), 7.0F);
            if (var6 < (double)(var8 + var11 / 2.0F)) {
               break;
            }

            var8 += var11;
         }

         this.selectionStart = Math.min(var9, this.getProperty().getValue().length());
         this.selectionEnd = this.selectionStart;
      }
   }

   @Override
   public void keyPressed(KeyInput keyInput) {
      if (this.focused) {
         if (keyInput.isSelectAll()) {
            this.selectionEnd = 0;
            this.selectionStart = this.getProperty().getValue().length();
         } else if (keyInput.isCopy()) {
            Constants.mc.keyboard.setClipboard(this.getSelectedText(this.getProperty().getValue()));
         } else if (keyInput.isPaste()) {
            this.paste();
         } else {
            SelectionType var2 = keyInput.hasCtrl() ? SelectionType.WORD : SelectionType.CHARACTER;
            int var3 = keyInput.key();
            if (var3 == 259) {
               this.delete(-1, var2);
            } else if (var3 == 261) {
               this.delete(1, var2);
            } else if (var3 == 263) {
               this.moveCursor(-1, keyInput.hasShift(), var2);
            } else if (var3 == 262) {
               this.moveCursor(1, keyInput.hasShift(), var2);
            }
         }
      }
   }

   @Override
   public void charTyped(char chr, int modifiers) {
      if (this.focused && StringHelper.isValidChar(chr)) {
         this.insert(Character.toString(chr));
      }
   }

   private void updateSelectionRange(boolean shiftDown) {
      if (!shiftDown) {
         this.selectionEnd = this.selectionStart;
      }
   }

   public void moveCursor(int offset, boolean shiftDown) {
      this.selectionStart = Util.moveCursor(this.getProperty().getValue(), this.selectionStart, offset);
      this.updateSelectionRange(shiftDown);
   }

   public void moveCursorPastWord(int offset, boolean shiftDown) {
      this.selectionStart = TextHandler.moveCursorByWords(this.getProperty().getValue(), offset, this.selectionStart, true);
      this.updateSelectionRange(shiftDown);
   }

   public void paste() {
      this.insert(Constants.mc.keyboard.getClipboard());
      this.selectionEnd = this.selectionStart;
   }

   public void moveCursor(int offset, boolean shiftDown, SelectionType selectionType) {
      switch (selectionType) {
         case CHARACTER:
            this.moveCursor(offset, shiftDown);
            break;
         case WORD:
            this.moveCursorPastWord(offset, shiftDown);
      }
   }

   private void insert(String insertion) {
      String var2 = this.getProperty().getValue();
      if (this.selectionEnd != this.selectionStart) {
         var2 = this.deleteSelectedText(var2);
      }

      this.selectionStart = MathHelper.clamp(this.selectionStart, 0, var2.length());
      String var3 = new StringBuilder(var2).insert(this.selectionStart, insertion).toString();
      this.getProperty().setValue(var3);
      this.selectionEnd = this.selectionStart = Math.min(var3.length(), this.selectionStart + insertion.length());
   }

   public void delete(int offset, SelectionType selectionType) {
      switch (selectionType) {
         case CHARACTER:
            this.delete(offset);
            break;
         case WORD:
            this.deleteWord(offset);
      }
   }

   public void deleteWord(int offset) {
      int var2 = TextHandler.moveCursorByWords(this.getProperty().getValue(), offset, this.selectionStart, true);
      this.delete(var2 - this.selectionStart);
   }

   public void delete(int offset) {
      if (!this.getProperty().getValue().isEmpty()) {
         String var2;
         if (this.selectionEnd != this.selectionStart) {
            var2 = this.deleteSelectedText(this.getProperty().getValue());
         } else {
            int var3 = Util.moveCursor(this.getProperty().getValue(), this.selectionStart, offset);
            int var4 = Math.min(var3, this.selectionStart);
            int var5 = Math.max(var3, this.selectionStart);
            var2 = new StringBuilder(this.getProperty().getValue()).delete(var4, var5).toString();
            if (offset < 0) {
               this.selectionEnd = this.selectionStart = var4;
            }
         }

         this.getProperty().setValue(var2);
      }
   }

   private String deleteSelectedText(String string) {
      if (this.selectionEnd == this.selectionStart) {
         return string;
      } else {
         int var2 = Math.min(this.selectionStart, this.selectionEnd);
         int var3 = Math.max(this.selectionStart, this.selectionEnd);
         this.selectionEnd = this.selectionStart = var2;
         return string.substring(0, var2) + string.substring(var3);
      }
   }

   private String getSelectedText(String string) {
      int var2 = Math.min(this.selectionStart, this.selectionEnd);
      int var3 = Math.max(this.selectionStart, this.selectionEnd);
      return string.substring(var2, var3);
   }
}
