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

import net.minecraft.world.level.levelgen.ChunkGeneratorSettings;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.LevelAccessor;
import java.util.List;
import net.minecraft.world.level.levelgen.structure.StructurePiece;
import java.util.Collection;
import net.minecraft.world.level.levelgen.structure.WoodlandMansionPieces;
import com.google.common.collect.Lists;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import java.util.Iterator;
import java.util.Set;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.ChunkPos;
import java.util.Random;
import net.minecraft.world.level.chunk.ChunkGenerator;
import com.mojang.datafixers.Dynamic;
import java.util.function.Function;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;

public class WoodlandMansionFeature extends StructureFeature<NoneFeatureConfiguration> {
    public WoodlandMansionFeature(final Function<Dynamic<?>, ? extends NoneFeatureConfiguration> function) {
        super(function);
    }
    
    @Override
    protected ChunkPos getPotentialFeatureChunkFromLocationWithOffset(final ChunkGenerator<?> caa, final Random random, final int integer3, final int integer4, final int integer5, final int integer6) {
        final int integer7 = ((ChunkGeneratorSettings)caa.getSettings()).getWoodlandMansionSpacing();
        final int integer8 = ((ChunkGeneratorSettings)caa.getSettings()).getWoodlandMangionSeparation();
        final int integer9 = integer3 + integer7 * integer5;
        final int integer10 = integer4 + integer7 * integer6;
        final int integer11 = (integer9 < 0) ? (integer9 - integer7 + 1) : integer9;
        final int integer12 = (integer10 < 0) ? (integer10 - integer7 + 1) : integer10;
        int integer13 = integer11 / integer7;
        int integer14 = integer12 / integer7;
        ((WorldgenRandom)random).setLargeFeatureWithSalt(caa.getSeed(), integer13, integer14, 10387319);
        integer13 *= integer7;
        integer14 *= integer7;
        integer13 += (random.nextInt(integer7 - integer8) + random.nextInt(integer7 - integer8)) / 2;
        integer14 += (random.nextInt(integer7 - integer8) + random.nextInt(integer7 - integer8)) / 2;
        return new ChunkPos(integer13, integer14);
    }
    
    @Override
    public boolean isFeatureChunk(final BiomeManager bkv, final ChunkGenerator<?> caa, final Random random, final int integer4, final int integer5, final Biome bkt) {
        final ChunkPos bjh8 = this.getPotentialFeatureChunkFromLocationWithOffset(caa, random, integer4, integer5, 0, 0);
        if (integer4 == bjh8.x && integer5 == bjh8.z) {
            final Set<Biome> set9 = caa.getBiomeSource().getBiomesWithin(integer4 * 16 + 9, caa.getSeaLevel(), integer5 * 16 + 9, 32);
            for (final Biome bkt2 : set9) {
                if (!caa.isBiomeValidStartForStructure(bkt2, this)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    
    @Override
    public StructureStartFactory getStartFactory() {
        return WoodlandMansionStart::new;
    }
    
    @Override
    public String getFeatureName() {
        return "Mansion";
    }
    
    @Override
    public int getLookupRange() {
        return 8;
    }
    
    public static class WoodlandMansionStart extends StructureStart {
        public WoodlandMansionStart(final StructureFeature<?> cfl, final int integer2, final int integer3, final BoundingBox clb, final int integer5, final long long6) {
            super(cfl, integer2, integer3, clb, integer5, long6);
        }
        
        @Override
        public void generatePieces(final ChunkGenerator<?> caa, final StructureManager cmo, final int integer3, final int integer4, final Biome bkt) {
            final Rotation btu7 = Rotation.values()[this.random.nextInt(Rotation.values().length)];
            int integer5 = 5;
            int integer6 = 5;
            if (btu7 == Rotation.CLOCKWISE_90) {
                integer5 = -5;
            }
            else if (btu7 == Rotation.CLOCKWISE_180) {
                integer5 = -5;
                integer6 = -5;
            }
            else if (btu7 == Rotation.COUNTERCLOCKWISE_90) {
                integer6 = -5;
            }
            final int integer7 = (integer3 << 4) + 7;
            final int integer8 = (integer4 << 4) + 7;
            final int integer9 = caa.getFirstOccupiedHeight(integer7, integer8, Heightmap.Types.WORLD_SURFACE_WG);
            final int integer10 = caa.getFirstOccupiedHeight(integer7, integer8 + integer6, Heightmap.Types.WORLD_SURFACE_WG);
            final int integer11 = caa.getFirstOccupiedHeight(integer7 + integer5, integer8, Heightmap.Types.WORLD_SURFACE_WG);
            final int integer12 = caa.getFirstOccupiedHeight(integer7 + integer5, integer8 + integer6, Heightmap.Types.WORLD_SURFACE_WG);
            final int integer13 = Math.min(Math.min(integer9, integer10), Math.min(integer11, integer12));
            if (integer13 < 60) {
                return;
            }
            final BlockPos fk17 = new BlockPos(integer3 * 16 + 8, integer13 + 1, integer4 * 16 + 8);
            final List<WoodlandMansionPieces.WoodlandMansionPiece> list18 = Lists.newLinkedList();
            WoodlandMansionPieces.generateMansion(cmo, fk17, btu7, list18, this.random);
            this.pieces.addAll(list18);
            this.calculateBoundingBox();
        }
        
        @Override
        public void postProcess(final LevelAccessor bjx, final ChunkGenerator<?> caa, final Random random, final BoundingBox clb, final ChunkPos bjh) {
            super.postProcess(bjx, caa, random, clb, bjh);
            final int integer7 = this.boundingBox.y0;
            for (int integer8 = clb.x0; integer8 <= clb.x1; ++integer8) {
                for (int integer9 = clb.z0; integer9 <= clb.z1; ++integer9) {
                    final BlockPos fk10 = new BlockPos(integer8, integer7, integer9);
                    if (!bjx.isEmptyBlock(fk10) && this.boundingBox.isInside(fk10)) {
                        boolean boolean11 = false;
                        for (final StructurePiece clu13 : this.pieces) {
                            if (clu13.getBoundingBox().isInside(fk10)) {
                                boolean11 = true;
                                break;
                            }
                        }
                        if (boolean11) {
                            for (int integer10 = integer7 - 1; integer10 > 1; --integer10) {
                                final BlockPos fk11 = new BlockPos(integer8, integer10, integer9);
                                if (!bjx.isEmptyBlock(fk11) && !bjx.getBlockState(fk11).getMaterial().isLiquid()) {
                                    break;
                                }
                                bjx.setBlock(fk11, Blocks.COBBLESTONE.defaultBlockState(), 2);
                            }
                        }
                    }
                }
            }
        }
    }
}
