package zenith.zov.utility.mixin.client;

import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.Box;
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import zenith.zov.Zenith;
import zenith.zov.client.modules.impl.combat.HitBox;
import zenith.zov.utility.interfaces.IMinecraft;

@Mixin({Entity.class})
public class EntityMixin implements IMinecraft {
    @ModifyExpressionValue(
        method = {"move"},
        at = {@At(
            value = "INVOKE",
            target = "Lnet/minecraft/entity/Entity;isControlledByPlayer()Z"
        )}
    )
    public boolean fixFalldistanceValue(boolean original) {
        return this == mc.player ? false : original;
    }

    @Redirect(
        method = {"updateVelocity"},
        at = @At(
            value = "INVOKE",
            target = "Lnet/minecraft/entity/Entity;getYaw()F"
        )
    )
    public float movementCorrection(Entity instance) {
        return instance instanceof ClientPlayerEntity ? Zenith.getInstance().getRotationManager().getCurrentRotation().getYaw() : instance.getYaw();
    }

    @ModifyVariable(
        method = {"getRotationVector(FF)Lnet/minecraft/util/math/Vec3d;"},
        at = @At("HEAD"),
        ordinal = 0,
        argsOnly = true
    )
    private float modifyPitch(float pitch) {
        return this instanceof ClientPlayerEntity ? Zenith.getInstance().getRotationManager().getCurrentRotation().getPitch() : pitch;
    }

    @ModifyVariable(
        method = {"getRotationVector(FF)Lnet/minecraft/util/math/Vec3d;"},
        at = @At("HEAD"),
        ordinal = 1,
        argsOnly = true
    )
    private float modifyYaw(float yaw) {
        return this instanceof ClientPlayerEntity ? Zenith.getInstance().getRotationManager().getCurrentRotation().getYaw() : yaw;
    }

    @Inject(
        method = {"getBoundingBox"},
        at = {@At("RETURN")},
        cancellable = true
    )
    private void modifyBoundingBox(CallbackInfoReturnable<Box> cir) {
        if (HitBox.INSTANCE.isEnabled()
            && this instanceof LivingEntity living
            && living != mc.player
            && !Zenith.getInstance().getFriendManager().isFriend(living.getName().getString())) {
            Box original = (Box)cir.getReturnValue();
            float xzExpand = HitBox.INSTANCE.getXzExpandSetting().getCurrent();
            float yExpand = HitBox.INSTANCE.getYExpandSetting().getCurrent();
            Box expanded = new Box(
                original.minX - (double)(xzExpand / 2.0F),
                original.minY - (double)(yExpand / 2.0F),
                original.minZ - (double)(xzExpand / 2.0F),
                original.maxX + (double)(xzExpand / 2.0F),
                original.maxY + (double)(yExpand / 2.0F),
                original.maxZ + (double)(xzExpand / 2.0F)
            );
            cir.setReturnValue(expanded);
        }
    }
}
