package net.minecraft.world.entity.projectile;

import net.minecraft.world.item.Items;
import net.minecraft.world.item.ArrowItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.Item;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.util.Mth;
import java.util.Optional;
import java.util.Iterator;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import java.util.Set;
import com.google.common.collect.ImmutableSet;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.level.Level;
import java.util.function.Predicate;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.level.ClipContext;
import javax.annotation.Nullable;
import net.minecraft.world.entity.Entity;

public final class ProjectileUtil {
    public static HitResult forwardsRaycast(final Entity akq1, final boolean boolean2, final boolean boolean3, @Nullable final Entity akq4, final ClipContext.Block a) {
        return forwardsRaycast(akq1, boolean2, boolean3, akq4, a, true, akq3 -> !akq3.isSpectator() && akq3.isPickable() && (boolean3 || !akq3.is(akq4)) && !akq3.noPhysics, akq1.getBoundingBox().expandTowards(akq1.getDeltaMovement()).inflate(1.0));
    }
    
    public static HitResult getHitResult(final Entity akq, final AABB cvf, final Predicate<Entity> predicate, final ClipContext.Block a, final boolean boolean5) {
        return forwardsRaycast(akq, boolean5, false, null, a, false, predicate, cvf);
    }
    
    @Nullable
    public static EntityHitResult getHitResult(final Level bjw, final Entity akq, final Vec3 cvl3, final Vec3 cvl4, final AABB cvf, final Predicate<Entity> predicate) {
        return getHitResult(bjw, akq, cvl3, cvl4, cvf, predicate, Double.MAX_VALUE);
    }
    
    private static HitResult forwardsRaycast(final Entity akq1, final boolean boolean2, final boolean boolean3, @Nullable final Entity akq4, final ClipContext.Block a, final boolean boolean6, final Predicate<Entity> predicate, final AABB cvf) {
        final Vec3 cvl9 = akq1.getDeltaMovement();
        final Level bjw10 = akq1.level;
        final Vec3 cvl10 = akq1.position();
        if (boolean6 && !bjw10.noCollision(akq1, akq1.getBoundingBox(), (Set<Entity>)((boolean3 || akq4 == null) ? ImmutableSet.of() : getIgnoredEntities(akq4)))) {
            return new BlockHitResult(cvl10, Direction.getNearest(cvl9.x, cvl9.y, cvl9.z), new BlockPos(akq1), false);
        }
        Vec3 cvl11 = cvl10.add(cvl9);
        HitResult cvi13 = bjw10.clip(new ClipContext(cvl10, cvl11, a, ClipContext.Fluid.NONE, akq1));
        if (boolean2) {
            if (cvi13.getType() != HitResult.Type.MISS) {
                cvl11 = cvi13.getLocation();
            }
            final HitResult cvi14 = getHitResult(bjw10, akq1, cvl10, cvl11, cvf, predicate);
            if (cvi14 != null) {
                cvi13 = cvi14;
            }
        }
        return cvi13;
    }
    
    @Nullable
    public static EntityHitResult getEntityHitResult(final Entity akq, final Vec3 cvl2, final Vec3 cvl3, final AABB cvf, final Predicate<Entity> predicate, final double double6) {
        final Level bjw8 = akq.level;
        double double7 = double6;
        Entity akq2 = null;
        Vec3 cvl4 = null;
        for (final Entity akq3 : bjw8.getEntities(akq, cvf, predicate)) {
            final AABB cvf2 = akq3.getBoundingBox().inflate(akq3.getPickRadius());
            final Optional<Vec3> optional16 = cvf2.clip(cvl2, cvl3);
            if (cvf2.contains(cvl2)) {
                if (double7 < 0.0) {
                    continue;
                }
                akq2 = akq3;
                cvl4 = optional16.orElse(cvl2);
                double7 = 0.0;
            }
            else {
                if (!optional16.isPresent()) {
                    continue;
                }
                final Vec3 cvl5 = optional16.get();
                final double double8 = cvl2.distanceToSqr(cvl5);
                if (double8 >= double7 && double7 != 0.0) {
                    continue;
                }
                if (akq3.getRootVehicle() == akq.getRootVehicle()) {
                    if (double7 != 0.0) {
                        continue;
                    }
                    akq2 = akq3;
                    cvl4 = cvl5;
                }
                else {
                    akq2 = akq3;
                    cvl4 = cvl5;
                    double7 = double8;
                }
            }
        }
        if (akq2 == null) {
            return null;
        }
        return new EntityHitResult(akq2, cvl4);
    }
    
    @Nullable
    public static EntityHitResult getHitResult(final Level bjw, final Entity akq, final Vec3 cvl3, final Vec3 cvl4, final AABB cvf, final Predicate<Entity> predicate, final double double7) {
        double double8 = double7;
        Entity akq2 = null;
        for (final Entity akq3 : bjw.getEntities(akq, cvf, predicate)) {
            final AABB cvf2 = akq3.getBoundingBox().inflate(0.30000001192092896);
            final Optional<Vec3> optional15 = cvf2.clip(cvl3, cvl4);
            if (optional15.isPresent()) {
                final double double9 = cvl3.distanceToSqr(optional15.get());
                if (double9 >= double8) {
                    continue;
                }
                akq2 = akq3;
                double8 = double9;
            }
        }
        if (akq2 == null) {
            return null;
        }
        return new EntityHitResult(akq2);
    }
    
    private static Set<Entity> getIgnoredEntities(final Entity akq) {
        final Entity akq2 = akq.getVehicle();
        return (akq2 != null) ? ImmutableSet.<Entity>of(akq, akq2) : ImmutableSet.<Entity>of(akq);
    }
    
    public static final void rotateTowardsMovement(final Entity akq, final float float2) {
        final Vec3 cvl3 = akq.getDeltaMovement();
        final float float3 = Mth.sqrt(Entity.getHorizontalDistanceSqr(cvl3));
        akq.yRot = (float)(Mth.atan2(cvl3.z, cvl3.x) * 57.2957763671875) + 90.0f;
        akq.xRot = (float)(Mth.atan2(float3, cvl3.y) * 57.2957763671875) - 90.0f;
        while (akq.xRot - akq.xRotO < -180.0f) {
            akq.xRotO -= 360.0f;
        }
        while (akq.xRot - akq.xRotO >= 180.0f) {
            akq.xRotO += 360.0f;
        }
        while (akq.yRot - akq.yRotO < -180.0f) {
            akq.yRotO -= 360.0f;
        }
        while (akq.yRot - akq.yRotO >= 180.0f) {
            akq.yRotO += 360.0f;
        }
        akq.xRot = Mth.lerp(float2, akq.xRotO, akq.xRot);
        akq.yRot = Mth.lerp(float2, akq.yRotO, akq.yRot);
    }
    
    public static InteractionHand getWeaponHoldingHand(final LivingEntity akz, final Item bei) {
        return (akz.getMainHandItem().getItem() == bei) ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
    }
    
    public static AbstractArrow getMobArrow(final LivingEntity akz, final ItemStack ben, final float float3) {
        final ArrowItem bck4 = (ArrowItem)((ben.getItem() instanceof ArrowItem) ? ben.getItem() : Items.ARROW);
        final AbstractArrow ayn5 = bck4.createArrow(akz.level, ben, akz);
        ayn5.setEnchantmentEffectsFromEntity(akz, float3);
        if (ben.getItem() == Items.TIPPED_ARROW && ayn5 instanceof Arrow) {
            ((Arrow)ayn5).setEffectsFromItem(ben);
        }
        return ayn5;
    }
}
