package net.minecraft.world.level.material;

import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.tags.Tag;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.LiquidBlock;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.LevelAccessor;
import javax.annotation.Nullable;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.GameRules;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.level.BlockGetter;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.Item;

public abstract class LavaFluid extends FlowingFluid {
    @Override
    public Fluid getFlowing() {
        return Fluids.FLOWING_LAVA;
    }
    
    @Override
    public Fluid getSource() {
        return Fluids.LAVA;
    }
    
    @Override
    public Item getBucket() {
        return Items.LAVA_BUCKET;
    }
    
    public void animateTick(final Level bqb, final BlockPos fu, final FluidState cxa, final Random random) {
        final BlockPos fu2 = fu.above();
        if (bqb.getBlockState(fu2).isAir() && !bqb.getBlockState(fu2).isSolidRender(bqb, fu2)) {
            if (random.nextInt(100) == 0) {
                final double double7 = fu.getX() + random.nextDouble();
                final double double8 = fu.getY() + 1.0;
                final double double9 = fu.getZ() + random.nextDouble();
                bqb.addParticle(ParticleTypes.LAVA, double7, double8, double9, 0.0, 0.0, 0.0);
                bqb.playLocalSound(double7, double8, double9, SoundEvents.LAVA_POP, SoundSource.BLOCKS, 0.2f + random.nextFloat() * 0.2f, 0.9f + random.nextFloat() * 0.15f, false);
            }
            if (random.nextInt(200) == 0) {
                bqb.playLocalSound(fu.getX(), fu.getY(), fu.getZ(), SoundEvents.LAVA_AMBIENT, SoundSource.BLOCKS, 0.2f + random.nextFloat() * 0.2f, 0.9f + random.nextFloat() * 0.15f, false);
            }
        }
    }
    
    public void randomTick(final Level bqb, final BlockPos fu, final FluidState cxa, final Random random) {
        if (!bqb.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
            return;
        }
        final int integer6 = random.nextInt(3);
        if (integer6 > 0) {
            BlockPos fu2 = fu;
            for (int integer7 = 0; integer7 < integer6; ++integer7) {
                fu2 = fu2.offset(random.nextInt(3) - 1, 1, random.nextInt(3) - 1);
                if (!bqb.isLoaded(fu2)) {
                    return;
                }
                final BlockState cfj9 = bqb.getBlockState(fu2);
                if (cfj9.isAir()) {
                    if (this.hasFlammableNeighbours(bqb, fu2)) {
                        bqb.setBlockAndUpdate(fu2, BaseFireBlock.getState(bqb, fu2));
                        return;
                    }
                }
                else if (cfj9.getMaterial().blocksMotion()) {
                    return;
                }
            }
        }
        else {
            for (int integer8 = 0; integer8 < 3; ++integer8) {
                final BlockPos fu3 = fu.offset(random.nextInt(3) - 1, 0, random.nextInt(3) - 1);
                if (!bqb.isLoaded(fu3)) {
                    return;
                }
                if (bqb.isEmptyBlock(fu3.above()) && this.isFlammable(bqb, fu3)) {
                    bqb.setBlockAndUpdate(fu3.above(), BaseFireBlock.getState(bqb, fu3));
                }
            }
        }
    }
    
    private boolean hasFlammableNeighbours(final LevelReader bqd, final BlockPos fu) {
        for (final Direction fz7 : Direction.values()) {
            if (this.isFlammable(bqd, fu.relative(fz7))) {
                return true;
            }
        }
        return false;
    }
    
    private boolean isFlammable(final LevelReader bqd, final BlockPos fu) {
        return (fu.getY() < 0 || fu.getY() >= 256 || bqd.hasChunkAt(fu)) && bqd.getBlockState(fu).getMaterial().isFlammable();
    }
    
    @Nullable
    public ParticleOptions getDripParticle() {
        return ParticleTypes.DRIPPING_LAVA;
    }
    
    @Override
    protected void beforeDestroyingBlock(final LevelAccessor bqc, final BlockPos fu, final BlockState cfj) {
        this.fizz(bqc, fu);
    }
    
    public int getSlopeFindDistance(final LevelReader bqd) {
        return bqd.dimensionType().ultraWarm() ? 4 : 2;
    }
    
    public BlockState createLegacyBlock(final FluidState cxa) {
        return ((StateHolder<O, BlockState>)Blocks.LAVA.defaultBlockState()).<Comparable, Integer>setValue((Property<Comparable>)LiquidBlock.LEVEL, FlowingFluid.getLegacyLevel(cxa));
    }
    
    @Override
    public boolean isSame(final Fluid cwz) {
        return cwz == Fluids.LAVA || cwz == Fluids.FLOWING_LAVA;
    }
    
    public int getDropOff(final LevelReader bqd) {
        return bqd.dimensionType().ultraWarm() ? 1 : 2;
    }
    
    public boolean canBeReplacedWith(final FluidState cxa, final BlockGetter bpg, final BlockPos fu, final Fluid cwz, final Direction fz) {
        return cxa.getHeight(bpg, fu) >= 0.44444445f && cwz.is(FluidTags.WATER);
    }
    
    @Override
    public int getTickDelay(final LevelReader bqd) {
        return bqd.dimensionType().ultraWarm() ? 10 : 30;
    }
    
    public int getSpreadDelay(final Level bqb, final BlockPos fu, final FluidState cxa3, final FluidState cxa4) {
        int integer6 = this.getTickDelay(bqb);
        if (!cxa3.isEmpty() && !cxa4.isEmpty() && !cxa3.<Boolean>getValue((Property<Boolean>)LavaFluid.FALLING) && !cxa4.<Boolean>getValue((Property<Boolean>)LavaFluid.FALLING) && cxa4.getHeight(bqb, fu) > cxa3.getHeight(bqb, fu) && bqb.getRandom().nextInt(4) != 0) {
            integer6 *= 4;
        }
        return integer6;
    }
    
    private void fizz(final LevelAccessor bqc, final BlockPos fu) {
        bqc.levelEvent(1501, fu, 0);
    }
    
    @Override
    protected boolean canConvertToSource() {
        return false;
    }
    
    @Override
    protected void spreadTo(final LevelAccessor bqc, final BlockPos fu, final BlockState cfj, final Direction fz, final FluidState cxa) {
        if (fz == Direction.DOWN) {
            final FluidState cxa2 = bqc.getFluidState(fu);
            if (this.is(FluidTags.LAVA) && cxa2.is(FluidTags.WATER)) {
                if (cfj.getBlock() instanceof LiquidBlock) {
                    bqc.setBlock(fu, Blocks.STONE.defaultBlockState(), 3);
                }
                this.fizz(bqc, fu);
                return;
            }
        }
        super.spreadTo(bqc, fu, cfj, fz, cxa);
    }
    
    @Override
    protected boolean isRandomlyTicking() {
        return true;
    }
    
    @Override
    protected float getExplosionResistance() {
        return 100.0f;
    }
    
    public static class Source extends LavaFluid {
        @Override
        public int getAmount(final FluidState cxa) {
            return 8;
        }
        
        @Override
        public boolean isSource(final FluidState cxa) {
            return true;
        }
    }
    
    public static class Flowing extends LavaFluid {
        @Override
        protected void createFluidStateDefinition(final StateDefinition.Builder<Fluid, FluidState> a) {
            super.createFluidStateDefinition(a);
            a.add(Flowing.LEVEL);
        }
        
        @Override
        public int getAmount(final FluidState cxa) {
            return cxa.<Integer>getValue((Property<Integer>)Flowing.LEVEL);
        }
        
        @Override
        public boolean isSource(final FluidState cxa) {
            return false;
        }
    }
}
