package dev.crucifixbeta.core.impl;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.eventbus.EventListener;
import dev.crucifixbeta.api.events.impl.GameLeftEvent;
import dev.crucifixbeta.api.events.impl.PacketEvent;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.api.utils.math.MathUtil;
import dev.crucifixbeta.api.utils.math.Timer;
import dev.crucifixbeta.mod.modules.impl.client.AntiCheat;
import dev.crucifixbeta.mod.modules.impl.client.Fonts;
import dev.crucifixbeta.mod.modules.impl.combat.Criticals;
import dev.crucifixbeta.mod.modules.impl.misc.AutoLog;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayDeque;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket;
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket.InteractType;
import net.minecraft.network.packet.s2c.play.ChatMessageS2CPacket;
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
import net.minecraft.network.packet.s2c.play.WorldTimeUpdateS2CPacket;

@Environment(EnvType.CLIENT)
public class ServerManager implements Wrapper {
   public final Timer playerNull = new Timer();
   public int currentSlot = -1;
   private final ArrayDeque<Float> tpsResult = new ArrayDeque<>(20);
   boolean worldNull = true;
   private long time;
   private long tickTime;
   private float tps;
   int lastSlot;

   public ServerManager() {
      CrucifixBeta.EVENT_BUS.subscribe(this);
   }

   public static float round2(double value) {
      BigDecimal var2 = new BigDecimal(value);
      var2 = var2.setScale(2, RoundingMode.HALF_UP);
      return var2.floatValue();
   }

   @EventListener(
      priority = -200
   )
   public void onPacket(PacketEvent.Send event) {
      if (AntiCheat.INSTANCE.attackCDFix.getValue()) {
         if (event.isCancelled()) {
            return;
         }

         Packet var2 = event.getPacket();
         if (!(var2 instanceof HandSwingC2SPacket)
            && (!(var2 instanceof PlayerInteractEntityC2SPacket) || Criticals.getInteractType((PlayerInteractEntityC2SPacket)var2) != InteractType.ATTACK)) {
            UpdateSelectedSlotC2SPacket var3;
            if (var2 instanceof UpdateSelectedSlotC2SPacket && this.lastSlot != (var3 = (UpdateSelectedSlotC2SPacket)var2).getSelectedSlot()) {
               this.lastSlot = var3.getSelectedSlot();
               mc.player.resetLastAttackedTicks();
            }
         } else {
            mc.player.resetLastAttackedTicks();
         }
      }
   }

   @EventListener
   public void onLeft(GameLeftEvent event) {
      this.currentSlot = -1;
   }

   @EventListener
   public void onPacketSend(PacketEvent.Send event) {
      if (event.getPacket() instanceof UpdateSelectedSlotC2SPacket var3) {
         int var4 = var3.getSelectedSlot();
         if (AntiCheat.INSTANCE.noBadSlot.getValue() && var4 == this.currentSlot) {
            event.cancel();
            return;
         }

         this.currentSlot = var4;
      }
   }

   public float getTPS() {
      return round2((double)this.tps);
   }

   public float getCurrentTPS() {
      return round2((double)(20.0F * ((float)this.tickTime / 1000.0F)));
   }

   public float getTPSFactor() {
      return this.getTPS() / 20.0F;
   }

   @EventListener(
      priority = 999
   )
   public void onPacketReceive(PacketEvent.Receive event) {
      if (event.getPacket() instanceof WorldTimeUpdateS2CPacket) {
         if (this.time != 0L) {
            this.tickTime = System.currentTimeMillis() - this.time;
            if (this.tpsResult.size() > 20) {
               this.tpsResult.poll();
            }

            this.tpsResult.add(20.0F * (1000.0F / (float)this.tickTime));
            float var2 = 0.0F;

            for (Float var4 : this.tpsResult) {
               var2 += MathUtil.clamp(var4, 0.0F, 20.0F);
            }

            this.tps = var2 / (float)this.tpsResult.size();
         }

         this.time = System.currentTimeMillis();
      }
   }

   @EventListener
   private void PacketReceive(PacketEvent.Receive event) {
      if (mc.player != null && mc.world != null) {
         String var2 = null;
         if (event.getPacket() instanceof GameMessageS2CPacket var4) {
            if (var4.content() != null) {
               var2 = var4.content().getString();
            }
         } else if (event.getPacket() instanceof ChatMessageS2CPacket var6) {
            var2 = var6.unsignedContent() != null ? var6.unsignedContent().getString() : var6.body().content();
         }

         if (var2 != null) {
         }
      }
   }

   public void onUpdate() {
      if (mc.player == null) {
         this.playerNull.reset();
      }

      if (this.worldNull && mc.world != null) {
         Fonts.INSTANCE.refresh();
         AutoLog.loggedOut = false;
         CrucifixBeta.MODULE.onLogin();
         this.worldNull = false;
      } else if (!this.worldNull && mc.world == null) {
         CrucifixBeta.save();
         CrucifixBeta.MODULE.onLogout();
         this.worldNull = true;
      }
   }
}
