package net.minecraft.world.entity.projectile;

import net.minecraft.world.level.block.state.AbstractStateHolder;
import org.apache.logging.log4j.LogManager;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.world.entity.monster.Blaze;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.AreaEffectCloud;
import net.minecraft.world.effect.MobEffect;
import javax.annotation.Nullable;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.damagesource.DamageSource;
import java.util.Iterator;
import net.minecraft.world.effect.MobEffectInstance;
import java.util.List;
import net.minecraft.world.item.alchemy.Potion;
import net.minecraft.world.entity.Entity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.core.Direction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.item.alchemy.Potions;
import net.minecraft.world.item.alchemy.PotionUtils;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import java.util.function.Predicate;
import org.apache.logging.log4j.Logger;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.syncher.EntityDataAccessor;

public class ThrownPotion extends ThrowableProjectile implements ItemSupplier {
    private static final EntityDataAccessor<ItemStack> DATA_ITEM_STACK;
    private static final Logger LOGGER;
    public static final Predicate<LivingEntity> WATER_SENSITIVE;
    
    public ThrownPotion(final EntityType<? extends ThrownPotion> aku, final Level bjw) {
        super(aku, bjw);
    }
    
    public ThrownPotion(final Level bjw, final LivingEntity akz) {
        super(EntityType.POTION, akz, bjw);
    }
    
    public ThrownPotion(final Level bjw, final double double2, final double double3, final double double4) {
        super(EntityType.POTION, double2, double3, double4, bjw);
    }
    
    @Override
    protected void defineSynchedData() {
        this.getEntityData().<ItemStack>define(ThrownPotion.DATA_ITEM_STACK, ItemStack.EMPTY);
    }
    
    @Override
    public ItemStack getItem() {
        final ItemStack ben2 = this.getEntityData().<ItemStack>get(ThrownPotion.DATA_ITEM_STACK);
        if (ben2.getItem() != Items.SPLASH_POTION && ben2.getItem() != Items.LINGERING_POTION) {
            if (this.level != null) {
                ThrownPotion.LOGGER.error("ThrownPotion entity {} has no item?!", this.getId());
            }
            return new ItemStack(Items.SPLASH_POTION);
        }
        return ben2;
    }
    
    public void setItem(final ItemStack ben) {
        this.getEntityData().<ItemStack>set(ThrownPotion.DATA_ITEM_STACK, ben.copy());
    }
    
    @Override
    protected float getGravity() {
        return 0.05f;
    }
    
    @Override
    protected void onHit(final HitResult cvi) {
        if (this.level.isClientSide) {
            return;
        }
        final ItemStack ben3 = this.getItem();
        final Potion bgd4 = PotionUtils.getPotion(ben3);
        final List<MobEffectInstance> list5 = PotionUtils.getMobEffects(ben3);
        final boolean boolean6 = bgd4 == Potions.WATER && list5.isEmpty();
        if (cvi.getType() == HitResult.Type.BLOCK && boolean6) {
            final BlockHitResult cvg7 = (BlockHitResult)cvi;
            final Direction fp8 = cvg7.getDirection();
            final BlockPos fk9 = cvg7.getBlockPos().relative(fp8);
            this.dowseFire(fk9, fp8);
            this.dowseFire(fk9.relative(fp8.getOpposite()), fp8);
            for (final Direction fp9 : Direction.Plane.HORIZONTAL) {
                this.dowseFire(fk9.relative(fp9), fp9);
            }
        }
        if (boolean6) {
            this.applyWater();
        }
        else if (!list5.isEmpty()) {
            if (this.isLingering()) {
                this.makeAreaOfEffectCloud(ben3, bgd4);
            }
            else {
                this.applySplash(list5, (cvi.getType() == HitResult.Type.ENTITY) ? ((EntityHitResult)cvi).getEntity() : null);
            }
        }
        final int integer7 = bgd4.hasInstantEffects() ? 2007 : 2002;
        this.level.levelEvent(integer7, new BlockPos(this), PotionUtils.getColor(ben3));
        this.remove();
    }
    
    private void applyWater() {
        final AABB cvf2 = this.getBoundingBox().inflate(4.0, 2.0, 4.0);
        final List<LivingEntity> list3 = this.level.<LivingEntity>getEntitiesOfClass(LivingEntity.class, cvf2, ThrownPotion.WATER_SENSITIVE);
        if (!list3.isEmpty()) {
            for (final LivingEntity akz5 : list3) {
                final double double6 = this.distanceToSqr(akz5);
                if (double6 < 16.0 && isWaterSensitiveEntity(akz5)) {
                    akz5.hurt(DamageSource.indirectMagic(akz5, this.getOwner()), 1.0f);
                }
            }
        }
    }
    
    private void applySplash(final List<MobEffectInstance> list, @Nullable final Entity akq) {
        final AABB cvf4 = this.getBoundingBox().inflate(4.0, 2.0, 4.0);
        final List<LivingEntity> list2 = this.level.<LivingEntity>getEntitiesOfClass(LivingEntity.class, cvf4);
        if (!list2.isEmpty()) {
            for (final LivingEntity akz7 : list2) {
                if (!akz7.isAffectedByPotions()) {
                    continue;
                }
                final double double8 = this.distanceToSqr(akz7);
                if (double8 >= 16.0) {
                    continue;
                }
                double double9 = 1.0 - Math.sqrt(double8) / 4.0;
                if (akz7 == akq) {
                    double9 = 1.0;
                }
                for (final MobEffectInstance akk13 : list) {
                    final MobEffect aki14 = akk13.getEffect();
                    if (aki14.isInstantenous()) {
                        aki14.applyInstantenousEffect(this, this.getOwner(), akz7, akk13.getAmplifier(), double9);
                    }
                    else {
                        final int integer15 = (int)(double9 * akk13.getDuration() + 0.5);
                        if (integer15 <= 20) {
                            continue;
                        }
                        akz7.addEffect(new MobEffectInstance(aki14, integer15, akk13.getAmplifier(), akk13.isAmbient(), akk13.isVisible()));
                    }
                }
            }
        }
    }
    
    private void makeAreaOfEffectCloud(final ItemStack ben, final Potion bgd) {
        final AreaEffectCloud akp4 = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ());
        akp4.setOwner(this.getOwner());
        akp4.setRadius(3.0f);
        akp4.setRadiusOnUse(-0.5f);
        akp4.setWaitTime(10);
        akp4.setRadiusPerTick(-akp4.getRadius() / akp4.getDuration());
        akp4.setPotion(bgd);
        for (final MobEffectInstance akk6 : PotionUtils.getCustomEffects(ben)) {
            akp4.addEffect(new MobEffectInstance(akk6));
        }
        final CompoundTag jt5 = ben.getTag();
        if (jt5 != null && jt5.contains("CustomPotionColor", 99)) {
            akp4.setFixedColor(jt5.getInt("CustomPotionColor"));
        }
        this.level.addFreshEntity(akp4);
    }
    
    private boolean isLingering() {
        return this.getItem().getItem() == Items.LINGERING_POTION;
    }
    
    private void dowseFire(final BlockPos fk, final Direction fp) {
        final BlockState byj4 = this.level.getBlockState(fk);
        final Block bph5 = byj4.getBlock();
        if (bph5 == Blocks.FIRE) {
            this.level.extinguishFire(null, fk.relative(fp), fp.getOpposite());
        }
        else if (bph5 == Blocks.CAMPFIRE && byj4.<Boolean>getValue((Property<Boolean>)CampfireBlock.LIT)) {
            this.level.levelEvent(null, 1009, fk, 0);
            this.level.setBlockAndUpdate(fk, ((AbstractStateHolder<O, BlockState>)byj4).<Comparable, Boolean>setValue((Property<Comparable>)CampfireBlock.LIT, false));
        }
    }
    
    @Override
    public void readAdditionalSaveData(final CompoundTag jt) {
        super.readAdditionalSaveData(jt);
        final ItemStack ben3 = ItemStack.of(jt.getCompound("Potion"));
        if (ben3.isEmpty()) {
            this.remove();
        }
        else {
            this.setItem(ben3);
        }
    }
    
    @Override
    public void addAdditionalSaveData(final CompoundTag jt) {
        super.addAdditionalSaveData(jt);
        final ItemStack ben3 = this.getItem();
        if (!ben3.isEmpty()) {
            jt.put("Potion", ben3.save(new CompoundTag()));
        }
    }
    
    private static boolean isWaterSensitiveEntity(final LivingEntity akz) {
        return akz instanceof EnderMan || akz instanceof Blaze;
    }
    
    static {
        DATA_ITEM_STACK = SynchedEntityData.<ItemStack>defineId(ThrownPotion.class, EntityDataSerializers.ITEM_STACK);
        LOGGER = LogManager.getLogger();
        WATER_SENSITIVE = ThrownPotion::isWaterSensitiveEntity;
    }
}
