package net.minecraft.world.level.levelgen;

import java.util.function.Function;
import net.minecraft.world.level.NoiseColumn;
import java.util.Arrays;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FixedBiomeSource;
import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings;
import com.mojang.serialization.Codec;
import net.minecraft.world.level.chunk.ChunkGenerator;

public class FlatLevelSource extends ChunkGenerator {
    public static final Codec<FlatLevelSource> CODEC;
    private final FlatLevelGeneratorSettings settings;
    
    public FlatLevelSource(final FlatLevelGeneratorSettings cra) {
        super(new FixedBiomeSource(cra.getBiomeFromSettings()), new FixedBiomeSource(cra.getBiome()), cra.structureSettings(), 0L);
        this.settings = cra;
    }
    
    @Override
    protected Codec<? extends ChunkGenerator> codec() {
        return FlatLevelSource.CODEC;
    }
    
    @Override
    public ChunkGenerator withSeed(final long long1) {
        return this;
    }
    
    public FlatLevelGeneratorSettings settings() {
        return this.settings;
    }
    
    @Override
    public void buildSurfaceAndBedrock(final WorldGenRegion zj, final ChunkAccess cgy) {
    }
    
    @Override
    public int getSpawnHeight() {
        final BlockState[] arr2 = this.settings.getLayers();
        for (int integer3 = 0; integer3 < arr2.length; ++integer3) {
            final BlockState cfj4 = (arr2[integer3] == null) ? Blocks.AIR.defaultBlockState() : arr2[integer3];
            if (!Heightmap.Types.MOTION_BLOCKING.isOpaque().test(cfj4)) {
                return integer3 - 1;
            }
        }
        return arr2.length;
    }
    
    @Override
    public void fillFromNoise(final LevelAccessor bqc, final StructureFeatureManager bqq, final ChunkAccess cgy) {
        final BlockState[] arr5 = this.settings.getLayers();
        final BlockPos.MutableBlockPos a6 = new BlockPos.MutableBlockPos();
        final Heightmap cio7 = cgy.getOrCreateHeightmapUnprimed(Heightmap.Types.OCEAN_FLOOR_WG);
        final Heightmap cio8 = cgy.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE_WG);
        for (int integer9 = 0; integer9 < arr5.length; ++integer9) {
            final BlockState cfj10 = arr5[integer9];
            if (cfj10 != null) {
                for (int integer10 = 0; integer10 < 16; ++integer10) {
                    for (int integer11 = 0; integer11 < 16; ++integer11) {
                        cgy.setBlockState(a6.set(integer10, integer9, integer11), cfj10, false);
                        cio7.update(integer10, integer9, integer11, cfj10);
                        cio8.update(integer10, integer9, integer11, cfj10);
                    }
                }
            }
        }
    }
    
    @Override
    public int getBaseHeight(final int integer1, final int integer2, final Heightmap.Types a) {
        final BlockState[] arr5 = this.settings.getLayers();
        for (int integer3 = arr5.length - 1; integer3 >= 0; --integer3) {
            final BlockState cfj7 = arr5[integer3];
            if (cfj7 != null) {
                if (a.isOpaque().test(cfj7)) {
                    return integer3 + 1;
                }
            }
        }
        return 0;
    }
    
    @Override
    public BlockGetter getBaseColumn(final int integer1, final int integer2) {
        return new NoiseColumn(Arrays.<BlockState>stream(this.settings.getLayers()).map(cfj -> (cfj == null) ? Blocks.AIR.defaultBlockState() : cfj).<BlockState>toArray(BlockState[]::new));
    }
    
    static {
        CODEC = FlatLevelGeneratorSettings.CODEC.fieldOf("settings").xmap((Function)FlatLevelSource::new, (Function)FlatLevelSource::settings).codec();
    }
}
