package dev.crucifixbeta.mod.modules.impl.movement;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.TickEvent;
import dev.crucifixbeta.api.events.impl.UpdateEvent;
import dev.crucifixbeta.api.utils.path.BaritoneUtil;
import dev.crucifixbeta.api.utils.player.EntityUtil;
import dev.crucifixbeta.api.utils.player.MovementUtil;
import dev.crucifixbeta.mod.modules.Module;
import dev.crucifixbeta.mod.modules.impl.combat.SelfTrap;
import dev.crucifixbeta.mod.modules.impl.combat.Surround;
import dev.crucifixbeta.mod.modules.settings.impl.BooleanSetting;
import dev.crucifixbeta.mod.modules.settings.impl.EnumSetting;
import dev.crucifixbeta.mod.modules.settings.impl.SliderSetting;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.PositionAndOnGround;

@Environment(EnvType.CLIENT)
public class Step extends Module {
   private final EnumSetting<Step.Mode> mode = this.add(new EnumSetting<>("Mode", Step.Mode.Vanilla));
   private final SliderSetting height = this.add(new SliderSetting("Height", 1.0, 0.0, 5.0, 0.5));
   private final BooleanSetting useTimer = this.add(
      new BooleanSetting("Timer", true, () -> this.mode.getValue() == Step.Mode.OldNCP || this.mode.getValue() == Step.Mode.NCP)
   );
   private final BooleanSetting fast = this.add(
      new BooleanSetting("Fast", true, () -> this.mode.getValue() == Step.Mode.NCP && this.useTimer.getValue())
   );
   private final BooleanSetting onlyMoving = this.add(new BooleanSetting("OnlyMoving", true));
   private final BooleanSetting surroundPause = this.add(new BooleanSetting("SurroundPause", true));
   private final BooleanSetting inWebPause = this.add(new BooleanSetting("InWebPause", true));
   private final BooleanSetting inBlockPause = this.add(new BooleanSetting("InBlockPause", true));
   private final BooleanSetting sneakingPause = this.add(new BooleanSetting("SneakingPause", true));
   private final BooleanSetting pathingPause = this.add(new BooleanSetting("PathingPause", true));
   boolean timer;
   int packets = 0;

   public Step() {
      super("Step", Module.Category.Movement);
      this.setChinese("\u6b65\u884c\u8f85\u52a9");
   }

   public static void setStepHeight(float v) {
      mc.player.getAttributeInstance(EntityAttributes.GENERIC_STEP_HEIGHT).setBaseValue((double)v);
   }

   @Override
   public void onDisable() {
      if (!nullCheck()) {
         setStepHeight(0.6F);
         CrucifixBeta.TIMER.reset();
      }
   }

   @Override
   public String getInfo() {
      return this.mode.getValue().name();
   }

   @EventListener
   public void onUpdate(UpdateEvent event) {
      if ((!this.pathingPause.getValue() || !BaritoneUtil.isActive())
         && (!this.sneakingPause.getValue() || !mc.player.isSneaking())
         && (!this.inBlockPause.getValue() || !EntityUtil.isInsideBlock())
         && !mc.player.isInLava()
         && !mc.player.isTouchingWater()
         && (!this.inWebPause.getValue() || !CrucifixBeta.PLAYER.isInWeb(mc.player))
         && mc.player.isOnGround()
         && (!this.onlyMoving.getValue() || MovementUtil.isMoving())
         && (!this.surroundPause.getValue() || !Surround.INSTANCE.isOn() && !SelfTrap.INSTANCE.isOn())) {
         setStepHeight(this.height.getValueFloat());
      } else {
         setStepHeight(0.6F);
      }
   }

   @EventListener
   public void onStep(TickEvent event) {
      if (event.isPost()) {
         this.packets--;
      } else {
         if (this.timer && this.packets <= 0) {
            CrucifixBeta.TIMER.reset();
            this.timer = false;
         }

         boolean var2 = this.mode.getValue() == Step.Mode.NCP;
         if (this.mode.getValue().equals(Step.Mode.OldNCP) || var2) {
            double var4 = mc.player.getY() - mc.player.prevY;
            if (var4 <= 0.75 || var4 > this.height.getValue()) {
               return;
            }

            double[] var6 = this.getOffset(var4);
            if (var6 != null && var6.length > 1) {
               if (this.useTimer.getValue()) {
                  CrucifixBeta.TIMER.set((float)this.getTimer(var4));
                  this.timer = true;
                  this.packets = 2;
               }

               for (double var10 : var6) {
                  mc.getNetworkHandler().sendPacket(new PositionAndOnGround(mc.player.prevX, mc.player.prevY + var10, mc.player.prevZ, false));
               }
            }
         }
      }
   }

   public double getTimer(double height) {
      if (height > 0.6 && height <= 1.0) {
         return !this.fast.getValue() && this.mode.getValue() == Step.Mode.NCP ? 0.3333333333333333 : 0.5;
      } else {
         double[] var3 = this.getOffset(height);
         return var3 == null ? 1.0 : 1.0 / (double)var3.length;
      }
   }

   public double[] getOffset(double height) {
      boolean var3 = this.mode.getValue() == Step.Mode.NCP;
      if (height == 0.75) {
         return var3 ? new double[]{0.42, 0.753, 0.75} : new double[]{0.42, 0.753};
      } else if (height == 0.8125) {
         return var3 ? new double[]{0.39, 0.7, 0.8125} : new double[]{0.39, 0.7};
      } else if (height == 0.875) {
         return var3 ? new double[]{0.39, 0.7, 0.875} : new double[]{0.39, 0.7};
      } else if (height == 1.0) {
         return var3 ? new double[]{0.42, 0.753, 1.0} : new double[]{0.42, 0.753};
      } else if (height == 1.5) {
         return new double[]{0.42, 0.75, 1.0, 1.16, 1.23, 1.2};
      } else if (height == 2.0) {
         return new double[]{0.42, 0.78, 0.63, 0.51, 0.9, 1.21, 1.45, 1.43};
      } else {
         return height == 2.5 ? new double[]{0.425, 0.821, 0.699, 0.599, 1.022, 1.372, 1.652, 1.869, 2.019, 1.907} : null;
      }
   }
@Environment(EnvType.CLIENT)
   public static enum Mode {
      Vanilla,
      OldNCP,
      NCP;

}
}
