package net.minecraft.world.level.levelgen.feature;

import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Iterator;
import net.minecraft.world.level.LevelWriter;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.WorldGenLevel;
import com.mojang.serialization.Codec;
import java.util.Random;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import com.google.common.collect.ImmutableList;
import net.minecraft.world.level.levelgen.feature.configurations.DeltaFeatureConfiguration;

public class DeltaFeature extends Feature<DeltaFeatureConfiguration> {
    private static final ImmutableList<Block> CANNOT_REPLACE;
    private static final Direction[] DIRECTIONS;
    
    private static int calculateRadius(final Random random, final DeltaFeatureConfiguration cno) {
        return cno.minimumRadius + random.nextInt(cno.maximumRadius - cno.minimumRadius + 1);
    }
    
    private static int calculateRimSize(final Random random, final DeltaFeatureConfiguration cno) {
        return random.nextInt(cno.maximumRimSize + 1);
    }
    
    public DeltaFeature(final Codec<DeltaFeatureConfiguration> codec) {
        super(codec);
    }
    
    @Override
    public boolean place(final WorldGenLevel bqu, final StructureFeatureManager bqq, final ChunkGenerator cha, final Random random, final BlockPos fu, final DeltaFeatureConfiguration cno) {
        final BlockPos fu2 = findDeltaLevel(bqu, fu.mutable().clamp(Direction.Axis.Y, 1, bqu.getMaxBuildHeight() - 1));
        if (fu2 == null) {
            return false;
        }
        boolean boolean9 = false;
        final boolean boolean10 = random.nextDouble() < 0.9;
        final int integer11 = boolean10 ? calculateRimSize(random, cno) : 0;
        final int integer12 = boolean10 ? calculateRimSize(random, cno) : 0;
        final boolean boolean11 = boolean10 && integer11 != 0 && integer12 != 0;
        final int integer13 = calculateRadius(random, cno);
        final int integer14 = calculateRadius(random, cno);
        final int integer15 = Math.max(integer13, integer14);
        for (final BlockPos fu3 : BlockPos.withinManhattan(fu2, integer13, 0, integer14)) {
            if (fu3.distManhattan(fu2) > integer15) {
                break;
            }
            if (!isClear(bqu, fu3, cno)) {
                continue;
            }
            if (boolean11) {
                boolean9 = true;
                this.setBlock(bqu, fu3, cno.rim);
            }
            final BlockPos fu4 = fu3.offset(integer11, 0, integer12);
            if (!isClear(bqu, fu4, cno)) {
                continue;
            }
            boolean9 = true;
            this.setBlock(bqu, fu4, cno.contents);
        }
        return boolean9;
    }
    
    private static boolean isClear(final LevelAccessor bqc, final BlockPos fu, final DeltaFeatureConfiguration cno) {
        final BlockState cfj4 = bqc.getBlockState(fu);
        if (cfj4.is(cno.contents.getBlock())) {
            return false;
        }
        if (DeltaFeature.CANNOT_REPLACE.contains(cfj4.getBlock())) {
            return false;
        }
        for (final Direction fz8 : DeltaFeature.DIRECTIONS) {
            final boolean boolean9 = bqc.getBlockState(fu.relative(fz8)).isAir();
            if ((boolean9 && fz8 != Direction.UP) || (!boolean9 && fz8 == Direction.UP)) {
                return false;
            }
        }
        return true;
    }
    
    @Nullable
    private static BlockPos findDeltaLevel(final LevelAccessor bqc, final BlockPos.MutableBlockPos a) {
        while (a.getY() > 1) {
            if (bqc.getBlockState(a).isAir()) {
                final BlockState cfj3 = bqc.getBlockState(a.move(Direction.DOWN));
                a.move(Direction.UP);
                if (!cfj3.is(Blocks.LAVA) && !cfj3.is(Blocks.BEDROCK) && !cfj3.isAir()) {
                    return a;
                }
            }
            a.move(Direction.DOWN);
        }
        return null;
    }
    
    static {
        CANNOT_REPLACE = ImmutableList.<Block>of(Blocks.BEDROCK, Blocks.NETHER_BRICKS, Blocks.NETHER_BRICK_FENCE, Blocks.NETHER_BRICK_STAIRS, Blocks.NETHER_WART, Blocks.CHEST, Blocks.SPAWNER);
        DIRECTIONS = Direction.values();
    }
}
