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

import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.ChunkGeneratorSettings;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Block;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.LevelWriter;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.core.BlockPos;
import java.util.Random;
import net.minecraft.world.level.LevelAccessor;
import com.mojang.datafixers.Dynamic;
import java.util.function.Function;
import net.minecraft.world.level.levelgen.feature.configurations.HugeMushroomFeatureConfiguration;

public abstract class AbstractHugeMushroomFeature extends Feature<HugeMushroomFeatureConfiguration> {
    public AbstractHugeMushroomFeature(final Function<Dynamic<?>, ? extends HugeMushroomFeatureConfiguration> function) {
        super(function);
    }
    
    protected void placeTrunk(final LevelAccessor bjx, final Random random, final BlockPos fk, final HugeMushroomFeatureConfiguration cgp, final int integer, final BlockPos.MutableBlockPos a) {
        for (int integer2 = 0; integer2 < integer; ++integer2) {
            a.set(fk).move(Direction.UP, integer2);
            if (!bjx.getBlockState(a).isSolidRender(bjx, a)) {
                this.setBlock(bjx, a, cgp.stemProvider.getState(random, fk));
            }
        }
    }
    
    protected int getTreeHeight(final Random random) {
        int integer3 = random.nextInt(3) + 4;
        if (random.nextInt(12) == 0) {
            integer3 *= 2;
        }
        return integer3;
    }
    
    protected boolean isValidPosition(final LevelAccessor bjx, final BlockPos fk, final int integer, final BlockPos.MutableBlockPos a, final HugeMushroomFeatureConfiguration cgp) {
        final int integer2 = fk.getY();
        if (integer2 < 1 || integer2 + integer + 1 >= 256) {
            return false;
        }
        final Block bph8 = bjx.getBlockState(fk.below()).getBlock();
        if (!Feature.isDirt(bph8)) {
            return false;
        }
        for (int integer3 = 0; integer3 <= integer; ++integer3) {
            for (int integer4 = this.getTreeRadiusForHeight(-1, -1, cgp.foliageRadius, integer3), integer5 = -integer4; integer5 <= integer4; ++integer5) {
                for (int integer6 = -integer4; integer6 <= integer4; ++integer6) {
                    final BlockState byj13 = bjx.getBlockState(a.set(fk).move(integer5, integer3, integer6));
                    if (!byj13.isAir() && !byj13.is(BlockTags.LEAVES)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    
    @Override
    public boolean place(final LevelAccessor bjx, final ChunkGenerator<? extends ChunkGeneratorSettings> caa, final Random random, final BlockPos fk, final HugeMushroomFeatureConfiguration cgp) {
        final int integer7 = this.getTreeHeight(random);
        final BlockPos.MutableBlockPos a8 = new BlockPos.MutableBlockPos();
        if (!this.isValidPosition(bjx, fk, integer7, a8, cgp)) {
            return false;
        }
        this.makeCap(bjx, random, fk, integer7, a8, cgp);
        this.placeTrunk(bjx, random, fk, cgp, integer7, a8);
        return true;
    }
    
    protected abstract int getTreeRadiusForHeight(final int integer1, final int integer2, final int integer3, final int integer4);
    
    protected abstract void makeCap(final LevelAccessor bjx, final Random random, final BlockPos fk, final int integer, final BlockPos.MutableBlockPos a, final HugeMushroomFeatureConfiguration cgp);
}
