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

import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelSimulatedReader;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import java.util.Set;
import net.minecraft.core.BlockPos;
import java.util.Random;
import net.minecraft.world.level.LevelSimulatedRW;
import com.mojang.datafixers.Dynamic;
import java.util.function.Function;
import net.minecraft.world.level.levelgen.feature.configurations.MegaTreeConfiguration;

public class DarkOakFeature extends AbstractTreeFeature<MegaTreeConfiguration> {
    public DarkOakFeature(final Function<Dynamic<?>, ? extends MegaTreeConfiguration> function) {
        super(function);
    }
    
    public boolean doPlace(final LevelSimulatedRW bkb, final Random random, final BlockPos fk, final Set<BlockPos> set4, final Set<BlockPos> set5, final BoundingBox clb, final MegaTreeConfiguration cgr) {
        final int integer9 = random.nextInt(3) + random.nextInt(2) + cgr.baseHeight;
        final int integer10 = fk.getX();
        final int integer11 = fk.getY();
        final int integer12 = fk.getZ();
        if (integer11 < 1 || integer11 + integer9 + 1 >= 256) {
            return false;
        }
        final BlockPos fk2 = fk.below();
        if (!AbstractTreeFeature.isGrassOrDirt(bkb, fk2)) {
            return false;
        }
        if (!this.canPlaceTreeOfHeight(bkb, fk, integer9)) {
            return false;
        }
        this.setDirtAt(bkb, fk2);
        this.setDirtAt(bkb, fk2.east());
        this.setDirtAt(bkb, fk2.south());
        this.setDirtAt(bkb, fk2.south().east());
        final Direction fp14 = Direction.Plane.HORIZONTAL.getRandomDirection(random);
        final int integer13 = integer9 - random.nextInt(4);
        int integer14 = 2 - random.nextInt(3);
        int integer15 = integer10;
        int integer16 = integer12;
        final int integer17 = integer11 + integer9 - 1;
        for (int integer18 = 0; integer18 < integer9; ++integer18) {
            if (integer18 >= integer13 && integer14 > 0) {
                integer15 += fp14.getStepX();
                integer16 += fp14.getStepZ();
                --integer14;
            }
            final int integer19 = integer11 + integer18;
            final BlockPos fk3 = new BlockPos(integer15, integer19, integer16);
            if (AbstractTreeFeature.isAirOrLeaves(bkb, fk3)) {
                this.placeLog(bkb, random, fk3, set4, clb, cgr);
                this.placeLog(bkb, random, fk3.east(), set4, clb, cgr);
                this.placeLog(bkb, random, fk3.south(), set4, clb, cgr);
                this.placeLog(bkb, random, fk3.east().south(), set4, clb, cgr);
            }
        }
        for (int integer18 = -2; integer18 <= 0; ++integer18) {
            for (int integer19 = -2; integer19 <= 0; ++integer19) {
                int integer20 = -1;
                this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18, integer17 + integer20, integer16 + integer19), set5, clb, cgr);
                this.placeLeaf(bkb, random, new BlockPos(1 + integer15 - integer18, integer17 + integer20, integer16 + integer19), set5, clb, cgr);
                this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18, integer17 + integer20, 1 + integer16 - integer19), set5, clb, cgr);
                this.placeLeaf(bkb, random, new BlockPos(1 + integer15 - integer18, integer17 + integer20, 1 + integer16 - integer19), set5, clb, cgr);
                if (integer18 > -2 || integer19 > -1) {
                    if (integer18 != -1 || integer19 != -2) {
                        integer20 = 1;
                        this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18, integer17 + integer20, integer16 + integer19), set5, clb, cgr);
                        this.placeLeaf(bkb, random, new BlockPos(1 + integer15 - integer18, integer17 + integer20, integer16 + integer19), set5, clb, cgr);
                        this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18, integer17 + integer20, 1 + integer16 - integer19), set5, clb, cgr);
                        this.placeLeaf(bkb, random, new BlockPos(1 + integer15 - integer18, integer17 + integer20, 1 + integer16 - integer19), set5, clb, cgr);
                    }
                }
            }
        }
        if (random.nextBoolean()) {
            this.placeLeaf(bkb, random, new BlockPos(integer15, integer17 + 2, integer16), set5, clb, cgr);
            this.placeLeaf(bkb, random, new BlockPos(integer15 + 1, integer17 + 2, integer16), set5, clb, cgr);
            this.placeLeaf(bkb, random, new BlockPos(integer15 + 1, integer17 + 2, integer16 + 1), set5, clb, cgr);
            this.placeLeaf(bkb, random, new BlockPos(integer15, integer17 + 2, integer16 + 1), set5, clb, cgr);
        }
        for (int integer18 = -3; integer18 <= 4; ++integer18) {
            for (int integer19 = -3; integer19 <= 4; ++integer19) {
                if ((integer18 != -3 || integer19 != -3) && (integer18 != -3 || integer19 != 4) && (integer18 != 4 || integer19 != -3)) {
                    if (integer18 != 4 || integer19 != 4) {
                        if (Math.abs(integer18) < 3 || Math.abs(integer19) < 3) {
                            this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18, integer17, integer16 + integer19), set5, clb, cgr);
                        }
                    }
                }
            }
        }
        for (int integer18 = -1; integer18 <= 2; ++integer18) {
            for (int integer19 = -1; integer19 <= 2; ++integer19) {
                if (integer18 < 0 || integer18 > 1 || integer19 < 0 || integer19 > 1) {
                    if (random.nextInt(3) <= 0) {
                        for (int integer20 = random.nextInt(3) + 2, integer21 = 0; integer21 < integer20; ++integer21) {
                            this.placeLog(bkb, random, new BlockPos(integer10 + integer18, integer17 - integer21 - 1, integer12 + integer19), set4, clb, cgr);
                        }
                        for (int integer21 = -1; integer21 <= 1; ++integer21) {
                            for (int integer22 = -1; integer22 <= 1; ++integer22) {
                                this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18 + integer21, integer17, integer16 + integer19 + integer22), set5, clb, cgr);
                            }
                        }
                        for (int integer21 = -2; integer21 <= 2; ++integer21) {
                            for (int integer22 = -2; integer22 <= 2; ++integer22) {
                                if (Math.abs(integer21) != 2 || Math.abs(integer22) != 2) {
                                    this.placeLeaf(bkb, random, new BlockPos(integer15 + integer18 + integer21, integer17 - 1, integer16 + integer19 + integer22), set5, clb, cgr);
                                }
                            }
                        }
                    }
                }
            }
        }
        return true;
    }
    
    private boolean canPlaceTreeOfHeight(final LevelSimulatedReader bkc, final BlockPos fk, final int integer) {
        final int integer2 = fk.getX();
        final int integer3 = fk.getY();
        final int integer4 = fk.getZ();
        final BlockPos.MutableBlockPos a8 = new BlockPos.MutableBlockPos();
        for (int integer5 = 0; integer5 <= integer + 1; ++integer5) {
            int integer6 = 1;
            if (integer5 == 0) {
                integer6 = 0;
            }
            if (integer5 >= integer - 1) {
                integer6 = 2;
            }
            for (int integer7 = -integer6; integer7 <= integer6; ++integer7) {
                for (int integer8 = -integer6; integer8 <= integer6; ++integer8) {
                    if (!AbstractTreeFeature.isFree(bkc, a8.set(integer2 + integer7, integer3 + integer5, integer4 + integer8))) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
}
