package net.minecraft.world.level.levelgen;

import net.minecraft.world.level.levelgen.surfacebuilders.ConfiguredSurfaceBuilder;
import java.util.Locale;
import net.minecraft.world.level.Level;
import javax.annotation.Nullable;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
import java.util.Iterator;
import java.util.Map;
import net.minecraft.world.level.levelgen.placement.ConfiguredDecorator;
import net.minecraft.world.level.levelgen.feature.configurations.DecoratorConfiguration;
import net.minecraft.world.level.levelgen.placement.FeatureDecorator;
import net.minecraft.world.level.levelgen.feature.configurations.LayerConfiguration;
import net.minecraft.world.level.levelgen.feature.Feature;
import com.google.common.collect.Lists;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.feature.configurations.DecoratedFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.npc.CatSpawner;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import net.minecraft.world.level.chunk.ChunkGenerator;

public class FlatLevelSource extends ChunkGenerator<FlatLevelGeneratorSettings> {
    private final Biome biomeWrapper;
    private final PhantomSpawner phantomSpawner;
    private final CatSpawner catSpawner;
    
    public FlatLevelSource(final LevelAccessor bjx, final BiomeSource bkw, final FlatLevelGeneratorSettings ciy) {
        super(bjx, bkw, ciy);
        this.phantomSpawner = new PhantomSpawner();
        this.catSpawner = new CatSpawner();
        this.biomeWrapper = this.getBiomeFromSettings();
    }
    
    private Biome getBiomeFromSettings() {
        final Biome bkt2 = ((FlatLevelGeneratorSettings)this.settings).getBiome();
        final FlatLevelBiomeWrapper a3 = new FlatLevelBiomeWrapper(bkt2.getSurfaceBuilder(), bkt2.getPrecipitation(), bkt2.getBiomeCategory(), bkt2.getDepth(), bkt2.getScale(), bkt2.getTemperature(), bkt2.getDownfall(), bkt2.getWaterColor(), bkt2.getWaterFogColor(), bkt2.getParent());
        final Map<String, Map<String, String>> map4 = ((FlatLevelGeneratorSettings)this.settings).getStructuresOptions();
        for (final String string6 : map4.keySet()) {
            final ConfiguredFeature<?, ?>[] arr7 = FlatLevelGeneratorSettings.STRUCTURE_FEATURES.get(string6);
            if (arr7 == null) {
                continue;
            }
            for (final ConfiguredFeature<?, ?> cdc11 : arr7) {
                a3.addFeature(FlatLevelGeneratorSettings.STRUCTURE_FEATURES_STEP.get(cdc11), cdc11);
                final ConfiguredFeature<?, ?> cdc12 = ((DecoratedFeatureConfiguration)cdc11.config).feature;
                if (cdc12.feature instanceof StructureFeature) {
                    final StructureFeature<FeatureConfiguration> cfl13 = (StructureFeature<FeatureConfiguration>)cdc12.feature;
                    final FeatureConfiguration cgn14 = bkt2.<FeatureConfiguration>getStructureConfiguration(cfl13);
                    final FeatureConfiguration cgn15 = (cgn14 != null) ? cgn14 : FlatLevelGeneratorSettings.STRUCTURE_FEATURES_DEFAULT.get(cdc11);
                    a3.<FeatureConfiguration>addStructureStart(cfl13.configured(cgn15));
                }
            }
        }
        final boolean boolean5 = (!((FlatLevelGeneratorSettings)this.settings).isVoidGen() || bkt2 == Biomes.THE_VOID) && map4.containsKey("decoration");
        if (boolean5) {
            final List<GenerationStep.Decoration> list6 = Lists.newArrayList();
            list6.add(GenerationStep.Decoration.UNDERGROUND_STRUCTURES);
            list6.add(GenerationStep.Decoration.SURFACE_STRUCTURES);
            for (final GenerationStep.Decoration b10 : GenerationStep.Decoration.values()) {
                if (!list6.contains(b10)) {
                    for (final ConfiguredFeature<?, ?> cdc12 : bkt2.getFeaturesForStep(b10)) {
                        a3.addFeature(b10, cdc12);
                    }
                }
            }
        }
        final BlockState[] arr8 = ((FlatLevelGeneratorSettings)this.settings).getLayers();
        for (int integer7 = 0; integer7 < arr8.length; ++integer7) {
            final BlockState byj8 = arr8[integer7];
            if (byj8 != null && !Heightmap.Types.MOTION_BLOCKING.isOpaque().test(byj8)) {
                ((FlatLevelGeneratorSettings)this.settings).deleteLayer(integer7);
                a3.addFeature(GenerationStep.Decoration.TOP_LAYER_MODIFICATION, Feature.FILL_LAYER.configured(new LayerConfiguration(integer7, byj8)).decorated(FeatureDecorator.NOPE.configured(DecoratorConfiguration.NONE)));
            }
        }
        return a3;
    }
    
    @Override
    public void buildSurfaceAndBedrock(final WorldGenRegion xj, final ChunkAccess bzy) {
    }
    
    @Override
    public int getSpawnHeight() {
        final ChunkAccess bzy2 = this.level.getChunk(0, 0);
        return bzy2.getHeight(Heightmap.Types.MOTION_BLOCKING, 8, 8);
    }
    
    @Override
    protected Biome getCarvingOrDecorationBiome(final BiomeManager bkv, final BlockPos fk) {
        return this.biomeWrapper;
    }
    
    @Override
    public void fillFromNoise(final LevelAccessor bjx, final ChunkAccess bzy) {
        final BlockState[] arr4 = ((FlatLevelGeneratorSettings)this.settings).getLayers();
        final BlockPos.MutableBlockPos a5 = new BlockPos.MutableBlockPos();
        final Heightmap cbv6 = bzy.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG);
        final Heightmap cbv7 = bzy.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG);
        for (int integer8 = 0; integer8 < arr4.length; ++integer8) {
            final BlockState byj9 = arr4[integer8];
            if (byj9 != null) {
                for (int integer9 = 0; integer9 < 16; ++integer9) {
                    for (int integer10 = 0; integer10 < 16; ++integer10) {
                        bzy.setBlockState(a5.set(integer9, integer8, integer10), byj9, false);
                        cbv6.update(integer9, integer8, integer10, byj9);
                        cbv7.update(integer9, integer8, integer10, byj9);
                    }
                }
            }
        }
    }
    
    @Override
    public int getBaseHeight(final int integer1, final int integer2, final Heightmap.Types a) {
        final BlockState[] arr5 = ((FlatLevelGeneratorSettings)this.settings).getLayers();
        for (int integer3 = arr5.length - 1; integer3 >= 0; --integer3) {
            final BlockState byj7 = arr5[integer3];
            if (byj7 != null) {
                if (a.isOpaque().test(byj7)) {
                    return integer3 + 1;
                }
            }
        }
        return 0;
    }
    
    @Override
    public void tickCustomSpawners(final ServerLevel xd, final boolean boolean2, final boolean boolean3) {
        this.phantomSpawner.tick(xd, boolean2, boolean3);
        this.catSpawner.tick(xd, boolean2, boolean3);
    }
    
    @Override
    public boolean isBiomeValidStartForStructure(final Biome bkt, final StructureFeature<? extends FeatureConfiguration> cfl) {
        return this.biomeWrapper.isValidStart(cfl);
    }
    
    @Nullable
    @Override
    public <C extends FeatureConfiguration> C getStructureConfiguration(final Biome bkt, final StructureFeature<C> cfl) {
        return this.biomeWrapper.<C>getStructureConfiguration(cfl);
    }
    
    @Nullable
    @Override
    public BlockPos findNearestMapFeature(final Level bjw, final String string, final BlockPos fk, final int integer, final boolean boolean5) {
        if (!((FlatLevelGeneratorSettings)this.settings).getStructuresOptions().keySet().contains(string.toLowerCase(Locale.ROOT))) {
            return null;
        }
        return super.findNearestMapFeature(bjw, string, fk, integer, boolean5);
    }
    
    class FlatLevelBiomeWrapper extends Biome {
        protected FlatLevelBiomeWrapper(final ConfiguredSurfaceBuilder<?> cmw, final Precipitation d, final BiomeCategory b, final float float5, final float float6, final float float7, final float float8, final int integer9, final int integer10, @Nullable final String string) {
            super(new BiomeBuilder().surfaceBuilder(cmw).precipitation(d).biomeCategory(b).depth(float5).scale(float6).temperature(float7).downfall(float8).waterColor(integer9).waterFogColor(integer10).parent(string));
        }
    }
}
