package net.minecraft.world.level.block.grower;

import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.block.Blocks;
import javax.annotation.Nullable;
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.BlockGetter;
import java.util.Random;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.server.level.ServerLevel;

public abstract class AbstractMegaTreeGrower extends AbstractTreeGrower {
    @Override
    public boolean growTree(final ServerLevel zd, final ChunkGenerator cha, final BlockPos fu, final BlockState cfj, final Random random) {
        for (int integer7 = 0; integer7 >= -1; --integer7) {
            for (int integer8 = 0; integer8 >= -1; --integer8) {
                if (isTwoByTwoSapling(cfj, zd, fu, integer7, integer8)) {
                    return this.placeMega(zd, cha, fu, cfj, random, integer7, integer8);
                }
            }
        }
        return super.growTree(zd, cha, fu, cfj, random);
    }
    
    @Nullable
    protected abstract ConfiguredFeature<TreeConfiguration, ?> getConfiguredMegaFeature(final Random random);
    
    public boolean placeMega(final ServerLevel zd, final ChunkGenerator cha, final BlockPos fu, final BlockState cfj, final Random random, final int integer6, final int integer7) {
        final ConfiguredFeature<TreeConfiguration, ?> ckb9 = this.getConfiguredMegaFeature(random);
        if (ckb9 == null) {
            return false;
        }
        ckb9.config.setFromSapling();
        final BlockState cfj2 = Blocks.AIR.defaultBlockState();
        zd.setBlock(fu.offset(integer6, 0, integer7), cfj2, 4);
        zd.setBlock(fu.offset(integer6 + 1, 0, integer7), cfj2, 4);
        zd.setBlock(fu.offset(integer6, 0, integer7 + 1), cfj2, 4);
        zd.setBlock(fu.offset(integer6 + 1, 0, integer7 + 1), cfj2, 4);
        if (ckb9.place(zd, zd.structureFeatureManager(), cha, random, fu.offset(integer6, 0, integer7))) {
            return true;
        }
        zd.setBlock(fu.offset(integer6, 0, integer7), cfj, 4);
        zd.setBlock(fu.offset(integer6 + 1, 0, integer7), cfj, 4);
        zd.setBlock(fu.offset(integer6, 0, integer7 + 1), cfj, 4);
        zd.setBlock(fu.offset(integer6 + 1, 0, integer7 + 1), cfj, 4);
        return false;
    }
    
    public static boolean isTwoByTwoSapling(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final int integer4, final int integer5) {
        final Block bvr6 = cfj.getBlock();
        return bvr6 == bpg.getBlockState(fu.offset(integer4, 0, integer5)).getBlock() && bvr6 == bpg.getBlockState(fu.offset(integer4 + 1, 0, integer5)).getBlock() && bvr6 == bpg.getBlockState(fu.offset(integer4, 0, integer5 + 1)).getBlock() && bvr6 == bpg.getBlockState(fu.offset(integer4 + 1, 0, integer5 + 1)).getBlock();
    }
}
