package net.minecraft.world.item;

import java.util.AbstractList;
import java.util.Collection;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import javax.annotation.Nullable;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.server.level.ServerPlayer;
import java.util.Random;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.entity.projectile.Projectile;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.world.entity.monster.CrossbowAttackMob;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
import com.google.common.collect.Lists;
import java.util.List;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import java.util.function.Predicate;

public class CrossbowItem extends ProjectileWeaponItem implements Vanishable {
    private boolean startSoundPlayed;
    private boolean midLoadSoundPlayed;
    
    public CrossbowItem(final Properties a) {
        super(a);
        this.startSoundPlayed = false;
        this.midLoadSoundPlayed = false;
    }
    
    @Override
    public Predicate<ItemStack> getSupportedHeldProjectiles() {
        return CrossbowItem.ARROW_OR_FIREWORK;
    }
    
    @Override
    public Predicate<ItemStack> getAllSupportedProjectiles() {
        return CrossbowItem.ARROW_ONLY;
    }
    
    @Override
    public InteractionResultHolder<ItemStack> use(final Level bqb, final Player bec, final InteractionHand anf) {
        final ItemStack bki5 = bec.getItemInHand(anf);
        if (isCharged(bki5)) {
            performShooting(bqb, bec, anf, bki5, getShootingPower(bki5), 1.0f);
            setCharged(bki5, false);
            return InteractionResultHolder.<ItemStack>consume(bki5);
        }
        if (!bec.getProjectile(bki5).isEmpty()) {
            if (!isCharged(bki5)) {
                this.startSoundPlayed = false;
                this.midLoadSoundPlayed = false;
                bec.startUsingItem(anf);
            }
            return InteractionResultHolder.<ItemStack>consume(bki5);
        }
        return InteractionResultHolder.<ItemStack>fail(bki5);
    }
    
    @Override
    public void releaseUsing(final ItemStack bki, final Level bqb, final LivingEntity aoy, final int integer) {
        final int integer2 = this.getUseDuration(bki) - integer;
        final float float7 = getPowerForTime(integer2, bki);
        if (float7 >= 1.0f && !isCharged(bki) && tryLoadProjectiles(aoy, bki)) {
            setCharged(bki, true);
            final SoundSource acm8 = (aoy instanceof Player) ? SoundSource.PLAYERS : SoundSource.HOSTILE;
            bqb.playSound(null, aoy.getX(), aoy.getY(), aoy.getZ(), SoundEvents.CROSSBOW_LOADING_END, acm8, 1.0f, 1.0f / (CrossbowItem.random.nextFloat() * 0.5f + 1.0f) + 0.2f);
        }
    }
    
    private static boolean tryLoadProjectiles(final LivingEntity aoy, final ItemStack bki) {
        final int integer3 = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.MULTISHOT, bki);
        final int integer4 = (integer3 == 0) ? 1 : 3;
        final boolean boolean5 = aoy instanceof Player && ((Player)aoy).abilities.instabuild;
        ItemStack bki2 = aoy.getProjectile(bki);
        ItemStack bki3 = bki2.copy();
        for (int integer5 = 0; integer5 < integer4; ++integer5) {
            if (integer5 > 0) {
                bki2 = bki3.copy();
            }
            if (bki2.isEmpty() && boolean5) {
                bki2 = new ItemStack(Items.ARROW);
                bki3 = bki2.copy();
            }
            if (!loadProjectile(aoy, bki, bki2, integer5 > 0, boolean5)) {
                return false;
            }
        }
        return true;
    }
    
    private static boolean loadProjectile(final LivingEntity aoy, final ItemStack bki2, final ItemStack bki3, final boolean boolean4, final boolean boolean5) {
        if (bki3.isEmpty()) {
            return false;
        }
        final boolean boolean6 = boolean5 && bki3.getItem() instanceof ArrowItem;
        ItemStack bki4;
        if (!boolean6 && !boolean5 && !boolean4) {
            bki4 = bki3.split(1);
            if (bki3.isEmpty() && aoy instanceof Player) {
                ((Player)aoy).inventory.removeItem(bki3);
            }
        }
        else {
            bki4 = bki3.copy();
        }
        addChargedProjectile(bki2, bki4);
        return true;
    }
    
    public static boolean isCharged(final ItemStack bki) {
        final CompoundTag le2 = bki.getTag();
        return le2 != null && le2.getBoolean("Charged");
    }
    
    public static void setCharged(final ItemStack bki, final boolean boolean2) {
        final CompoundTag le3 = bki.getOrCreateTag();
        le3.putBoolean("Charged", boolean2);
    }
    
    private static void addChargedProjectile(final ItemStack bki1, final ItemStack bki2) {
        final CompoundTag le3 = bki1.getOrCreateTag();
        ListTag lk4;
        if (le3.contains("ChargedProjectiles", 9)) {
            lk4 = le3.getList("ChargedProjectiles", 10);
        }
        else {
            lk4 = new ListTag();
        }
        final CompoundTag le4 = new CompoundTag();
        bki2.save(le4);
        ((AbstractList<CompoundTag>)lk4).add(le4);
        le3.put("ChargedProjectiles", lk4);
    }
    
    private static List<ItemStack> getChargedProjectiles(final ItemStack bki) {
        final List<ItemStack> list2 = Lists.newArrayList();
        final CompoundTag le3 = bki.getTag();
        if (le3 != null && le3.contains("ChargedProjectiles", 9)) {
            final ListTag lk4 = le3.getList("ChargedProjectiles", 10);
            if (lk4 != null) {
                for (int integer5 = 0; integer5 < lk4.size(); ++integer5) {
                    final CompoundTag le4 = lk4.getCompound(integer5);
                    list2.add(ItemStack.of(le4));
                }
            }
        }
        return list2;
    }
    
    private static void clearChargedProjectiles(final ItemStack bki) {
        final CompoundTag le2 = bki.getTag();
        if (le2 != null) {
            final ListTag lk3 = le2.getList("ChargedProjectiles", 9);
            lk3.clear();
            le2.put("ChargedProjectiles", lk3);
        }
    }
    
    public static boolean containsChargedProjectile(final ItemStack bki, final Item bke) {
        return getChargedProjectiles(bki).stream().anyMatch(bki -> bki.getItem() == bke);
    }
    
    private static void shootProjectile(final Level bqb, final LivingEntity aoy, final InteractionHand anf, final ItemStack bki4, final ItemStack bki5, final float float6, final boolean boolean7, final float float8, final float float9, final float float10) {
        if (bqb.isClientSide) {
            return;
        }
        final boolean boolean8 = bki5.getItem() == Items.FIREWORK_ROCKET;
        Projectile bes12;
        if (boolean8) {
            bes12 = new FireworkRocketEntity(bqb, bki5, aoy, aoy.getX(), aoy.getEyeY() - 0.15000000596046448, aoy.getZ(), true);
        }
        else {
            bes12 = getArrow(bqb, aoy, bki4, bki5);
            if (boolean7 || float10 != 0.0f) {
                ((AbstractArrow)bes12).pickup = AbstractArrow.Pickup.CREATIVE_ONLY;
            }
        }
        if (aoy instanceof CrossbowAttackMob) {
            final CrossbowAttackMob bbo13 = (CrossbowAttackMob)aoy;
            bbo13.shootCrossbowProjectile(bbo13.getTarget(), bki4, bes12, float10);
        }
        else {
            final Vec3 dem13 = aoy.getUpVector(1.0f);
            final Quaternion d14 = new Quaternion(new Vector3f(dem13), float10, true);
            final Vec3 dem14 = aoy.getViewVector(1.0f);
            final Vector3f g16 = new Vector3f(dem14);
            g16.transform(d14);
            bes12.shoot(g16.x(), g16.y(), g16.z(), float8, float9);
        }
        bki4.<LivingEntity>hurtAndBreak(boolean8 ? 3 : 1, aoy, aoy -> aoy.broadcastBreakEvent(anf));
        bqb.addFreshEntity(bes12);
        bqb.playSound(null, aoy.getX(), aoy.getY(), aoy.getZ(), SoundEvents.CROSSBOW_SHOOT, SoundSource.PLAYERS, 1.0f, float6);
    }
    
    private static AbstractArrow getArrow(final Level bqb, final LivingEntity aoy, final ItemStack bki3, final ItemStack bki4) {
        final ArrowItem bih5 = (ArrowItem)((bki4.getItem() instanceof ArrowItem) ? bki4.getItem() : Items.ARROW);
        final AbstractArrow beg6 = bih5.createArrow(bqb, bki4, aoy);
        if (aoy instanceof Player) {
            beg6.setCritArrow(true);
        }
        beg6.setSoundEvent(SoundEvents.CROSSBOW_HIT);
        beg6.setShotFromCrossbow(true);
        final int integer7 = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.PIERCING, bki3);
        if (integer7 > 0) {
            beg6.setPierceLevel((byte)integer7);
        }
        return beg6;
    }
    
    public static void performShooting(final Level bqb, final LivingEntity aoy, final InteractionHand anf, final ItemStack bki, final float float5, final float float6) {
        final List<ItemStack> list7 = getChargedProjectiles(bki);
        final float[] arr8 = getShotPitches(aoy.getRandom());
        for (int integer9 = 0; integer9 < list7.size(); ++integer9) {
            final ItemStack bki2 = list7.get(integer9);
            final boolean boolean11 = aoy instanceof Player && ((Player)aoy).abilities.instabuild;
            if (!bki2.isEmpty()) {
                if (integer9 == 0) {
                    shootProjectile(bqb, aoy, anf, bki, bki2, arr8[integer9], boolean11, float5, float6, 0.0f);
                }
                else if (integer9 == 1) {
                    shootProjectile(bqb, aoy, anf, bki, bki2, arr8[integer9], boolean11, float5, float6, -10.0f);
                }
                else if (integer9 == 2) {
                    shootProjectile(bqb, aoy, anf, bki, bki2, arr8[integer9], boolean11, float5, float6, 10.0f);
                }
            }
        }
        onCrossbowShot(bqb, aoy, bki);
    }
    
    private static float[] getShotPitches(final Random random) {
        final boolean boolean2 = random.nextBoolean();
        return new float[] { 1.0f, getRandomShotPitch(boolean2), getRandomShotPitch(!boolean2) };
    }
    
    private static float getRandomShotPitch(final boolean boolean1) {
        final float float2 = boolean1 ? 0.63f : 0.43f;
        return 1.0f / (CrossbowItem.random.nextFloat() * 0.5f + 1.8f) + float2;
    }
    
    private static void onCrossbowShot(final Level bqb, final LivingEntity aoy, final ItemStack bki) {
        if (aoy instanceof ServerPlayer) {
            final ServerPlayer ze4 = (ServerPlayer)aoy;
            if (!bqb.isClientSide) {
                CriteriaTriggers.SHOT_CROSSBOW.trigger(ze4, bki);
            }
            ze4.awardStat(Stats.ITEM_USED.get(bki.getItem()));
        }
        clearChargedProjectiles(bki);
    }
    
    @Override
    public void onUseTick(final Level bqb, final LivingEntity aoy, final ItemStack bki, final int integer) {
        if (!bqb.isClientSide) {
            final int integer2 = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, bki);
            final SoundEvent ack7 = this.getStartSound(integer2);
            final SoundEvent ack8 = (integer2 == 0) ? SoundEvents.CROSSBOW_LOADING_MIDDLE : null;
            final float float9 = (bki.getUseDuration() - integer) / (float)getChargeDuration(bki);
            if (float9 < 0.2f) {
                this.startSoundPlayed = false;
                this.midLoadSoundPlayed = false;
            }
            if (float9 >= 0.2f && !this.startSoundPlayed) {
                this.startSoundPlayed = true;
                bqb.playSound(null, aoy.getX(), aoy.getY(), aoy.getZ(), ack7, SoundSource.PLAYERS, 0.5f, 1.0f);
            }
            if (float9 >= 0.5f && ack8 != null && !this.midLoadSoundPlayed) {
                this.midLoadSoundPlayed = true;
                bqb.playSound(null, aoy.getX(), aoy.getY(), aoy.getZ(), ack8, SoundSource.PLAYERS, 0.5f, 1.0f);
            }
        }
    }
    
    @Override
    public int getUseDuration(final ItemStack bki) {
        return getChargeDuration(bki) + 3;
    }
    
    public static int getChargeDuration(final ItemStack bki) {
        final int integer2 = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.QUICK_CHARGE, bki);
        return (integer2 == 0) ? 25 : (25 - 5 * integer2);
    }
    
    @Override
    public UseAnim getUseAnimation(final ItemStack bki) {
        return UseAnim.CROSSBOW;
    }
    
    private SoundEvent getStartSound(final int integer) {
        switch (integer) {
            case 1: {
                return SoundEvents.CROSSBOW_QUICK_CHARGE_1;
            }
            case 2: {
                return SoundEvents.CROSSBOW_QUICK_CHARGE_2;
            }
            case 3: {
                return SoundEvents.CROSSBOW_QUICK_CHARGE_3;
            }
            default: {
                return SoundEvents.CROSSBOW_LOADING_START;
            }
        }
    }
    
    private static float getPowerForTime(final int integer, final ItemStack bki) {
        float float3 = integer / (float)getChargeDuration(bki);
        if (float3 > 1.0f) {
            float3 = 1.0f;
        }
        return float3;
    }
    
    @Override
    public void appendHoverText(final ItemStack bki, @Nullable final Level bqb, final List<Component> list, final TooltipFlag bls) {
        final List<ItemStack> list2 = getChargedProjectiles(bki);
        if (!isCharged(bki) || list2.isEmpty()) {
            return;
        }
        final ItemStack bki2 = list2.get(0);
        list.add(new TranslatableComponent("item.minecraft.crossbow.projectile").append(" ").append(bki2.getDisplayName()));
        if (bls.isAdvanced() && bki2.getItem() == Items.FIREWORK_ROCKET) {
            final List<Component> list3 = Lists.newArrayList();
            Items.FIREWORK_ROCKET.appendHoverText(bki2, bqb, list3, bls);
            if (!list3.isEmpty()) {
                for (int integer9 = 0; integer9 < list3.size(); ++integer9) {
                    list3.set(integer9, new TextComponent("  ").append(list3.get(integer9)).withStyle(ChatFormatting.GRAY));
                }
                list.addAll(list3);
            }
        }
    }
    
    private static float getShootingPower(final ItemStack bki) {
        if (bki.getItem() == Items.CROSSBOW && containsChargedProjectile(bki, Items.FIREWORK_ROCKET)) {
            return 1.6f;
        }
        return 3.15f;
    }
    
    @Override
    public int getDefaultProjectileRange() {
        return 8;
    }
}
