package asm.mixins;

import dev.crucifixbeta.CrucifixBeta;
import dev.crucifixbeta.api.events.Event;
import dev.crucifixbeta.api.events.impl.JumpEvent;
import dev.crucifixbeta.api.events.impl.TravelEvent;
import dev.crucifixbeta.api.utils.Wrapper;
import dev.crucifixbeta.mod.modules.impl.client.ClientSetting;
import dev.crucifixbeta.mod.modules.impl.player.InteractTweaks;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Environment(EnvType.CLIENT)
@Mixin({PlayerEntity.class})
public class MixinPlayerEntity implements Wrapper {
   @Inject(
      method = {"canChangeIntoPose"},
      at = {@At("RETURN")},
      cancellable = true
   )
   private void poseNotCollide(EntityPose pose, CallbackInfoReturnable<Boolean> cir) {
      if (PlayerEntity.class.cast(this) == mc.player && !ClientSetting.INSTANCE.crawl.getValue() && pose == EntityPose.SWIMMING) {
         cir.setReturnValue(false);
      }
   }

   @Inject(
      method = {"getBlockInteractionRange"},
      at = {@At("HEAD")},
      cancellable = true
   )
   public void getBlockInteractionRangeHook(CallbackInfoReturnable<Double> cir) {
      if (InteractTweaks.INSTANCE.reach()) {
         cir.setReturnValue(InteractTweaks.INSTANCE.blockRange.getValue());
      }
   }

   @Inject(
      method = {"getEntityInteractionRange"},
      at = {@At("HEAD")},
      cancellable = true
   )
   public void getEntityInteractionRangeHook(CallbackInfoReturnable<Double> cir) {
      if (InteractTweaks.INSTANCE.reach()) {
         cir.setReturnValue(InteractTweaks.INSTANCE.entityRange.getValue());
      }
   }

   @Inject(
      method = {"jump"},
      at = {@At("HEAD")}
   )
   private void onJumpPre(CallbackInfo ci) {
      CrucifixBeta.EVENT_BUS.post(JumpEvent.get(Event.Stage.Pre));
   }

   @Inject(
      method = {"jump"},
      at = {@At("RETURN")}
   )
   private void onJumpPost(CallbackInfo ci) {
      CrucifixBeta.EVENT_BUS.post(JumpEvent.get(Event.Stage.Post));
   }

   @Inject(
      method = {"travel"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void onTravelPre(Vec3d movementInput, CallbackInfo ci) {
      PlayerEntity var3 = PlayerEntity.class.cast(this);
      if (var3 == mc.player) {
         TravelEvent var4 = TravelEvent.get(Event.Stage.Pre, var3);
         CrucifixBeta.EVENT_BUS.post(var4);
         if (var4.isCancelled()) {
            ci.cancel();
            var4 = TravelEvent.get(Event.Stage.Post, var3);
            CrucifixBeta.EVENT_BUS.post(var4);
         }
      }
   }

   @Inject(
      method = {"travel"},
      at = {@At("RETURN")}
   )
   private void onTravelPost(Vec3d movementInput, CallbackInfo ci) {
      PlayerEntity var3 = PlayerEntity.class.cast(this);
      if (var3 == mc.player) {
         TravelEvent var4 = TravelEvent.get(Event.Stage.Post, var3);
         CrucifixBeta.EVENT_BUS.post(var4);
      }
   }
}
