package asm.mixins;

import dev.crucifixbeta.mod.features.SpearPort;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUsageContext;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.UseAction;
import net.minecraft.world.World;
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({ItemStack.class})
public abstract class MixinSpearItemStack {
   @Inject(
      method = {"use"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$startUsingPortedSpear(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> cir) {
      ItemStack var5 = (ItemStack)(Object)this;
      if (SpearPort.isSpear(var5)) {
         startUsingSpear(var5, world, user, hand);
         cir.setReturnValue(TypedActionResult.consume(var5));
      }
   }

   @Inject(
      method = {"useOnBlock"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$blockPortedSpearPlaceOnBlock(ItemUsageContext context, CallbackInfoReturnable<ActionResult> cir) {
      ItemStack var3 = (ItemStack)(Object)this;
      PlayerEntity var4 = context.getPlayer();
      if (var4 != null && SpearPort.isSpear(var3)) {
         startUsingSpear(var3, context.getWorld(), var4, context.getHand());
         cir.setReturnValue(ActionResult.CONSUME);
      }
   }

   @Inject(
      method = {"getMaxUseTime"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$getPortedSpearUseTime(LivingEntity user, CallbackInfoReturnable<Integer> cir) {
      if (SpearPort.isSpear((ItemStack)(Object)this)) {
         cir.setReturnValue(72000);
      }
   }

   @Inject(
      method = {"getUseAction"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$getPortedSpearUseAction(CallbackInfoReturnable<UseAction> cir) {
      if (SpearPort.isSpear((ItemStack)(Object)this)) {
         cir.setReturnValue(UseAction.NONE);
      }
   }

   @Inject(
      method = {"getName"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$fixPortedSpearName(CallbackInfoReturnable<Text> cir) {
      ItemStack var2 = (ItemStack)(Object)this;
      Text var3 = SpearPort.getNameOverride(var2);
      if (var3 != null) {
         cir.setReturnValue(var3);
      }
   }

   @Inject(
      method = {"onStoppedUsing"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$stopUsingPortedSpear(World world, LivingEntity user, int remainingUseTicks, CallbackInfo ci) {
      ItemStack var5 = (ItemStack)(Object)this;
      if (SpearPort.isSpear(var5)) {
         SpearPort.onStoppedUsing(var5, world, user, remainingUseTicks);
         ci.cancel();
      }
   }

   @Inject(
      method = {"usageTick"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$tickPortedSpear(World world, LivingEntity user, int remainingUseTicks, CallbackInfo ci) {
      ItemStack var5 = (ItemStack)(Object)this;
      if (SpearPort.isSpear(var5)) {
         SpearPort.onUsageTick(var5, world, user, remainingUseTicks);
         ci.cancel();
      }
   }

   @Inject(
      method = {"isUsedOnRelease"},
      at = {@At("HEAD")},
      cancellable = true
   )
   private void crucifix$isPortedSpearUsedOnRelease(CallbackInfoReturnable<Boolean> cir) {
      if (SpearPort.isSpear((ItemStack)(Object)this)) {
         cir.setReturnValue(true);
      }
   }

   private static void startUsingSpear(ItemStack stack, World world, PlayerEntity user, Hand hand) {
      user.setCurrentHand(hand);
      SpearPort.playUseSound(world, user, stack);
   }
}
