package net.minecraft.world.level.biome;

import com.google.common.collect.Lists;
import java.util.Iterator;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import java.util.Random;
import com.google.common.collect.Sets;
import com.google.common.collect.Maps;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Set;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import java.util.Map;
import java.util.List;

public abstract class BiomeSource implements BiomeManager.NoiseBiomeSource {
    private static final List<Biome> PLAYER_SPAWN_BIOMES;
    protected final Map<StructureFeature<?>, Boolean> supportedStructures;
    protected final Set<BlockState> surfaceBlocks;
    protected final Set<Biome> possibleBiomes;
    
    protected BiomeSource(final Set<Biome> set) {
        this.supportedStructures = Maps.newHashMap();
        this.surfaceBlocks = Sets.newHashSet();
        this.possibleBiomes = set;
    }
    
    public List<Biome> getPlayerSpawnBiomes() {
        return BiomeSource.PLAYER_SPAWN_BIOMES;
    }
    
    public Set<Biome> getBiomesWithin(final int integer1, final int integer2, final int integer3, final int integer4) {
        final int integer5 = integer1 - integer4 >> 2;
        final int integer6 = integer2 - integer4 >> 2;
        final int integer7 = integer3 - integer4 >> 2;
        final int integer8 = integer1 + integer4 >> 2;
        final int integer9 = integer2 + integer4 >> 2;
        final int integer10 = integer3 + integer4 >> 2;
        final int integer11 = integer8 - integer5 + 1;
        final int integer12 = integer9 - integer6 + 1;
        final int integer13 = integer10 - integer7 + 1;
        final Set<Biome> set15 = Sets.newHashSet();
        for (int integer14 = 0; integer14 < integer13; ++integer14) {
            for (int integer15 = 0; integer15 < integer11; ++integer15) {
                for (int integer16 = 0; integer16 < integer12; ++integer16) {
                    final int integer17 = integer5 + integer15;
                    final int integer18 = integer6 + integer16;
                    final int integer19 = integer7 + integer14;
                    set15.add(this.getNoiseBiome(integer17, integer18, integer19));
                }
            }
        }
        return set15;
    }
    
    @Nullable
    public BlockPos findBiomeHorizontal(final int integer1, final int integer2, final int integer3, final int integer4, final List<Biome> list, final Random random) {
        final int integer5 = integer1 - integer4 >> 2;
        final int integer6 = integer3 - integer4 >> 2;
        final int integer7 = integer1 + integer4 >> 2;
        final int integer8 = integer3 + integer4 >> 2;
        final int integer9 = integer7 - integer5 + 1;
        final int integer10 = integer8 - integer6 + 1;
        final int integer11 = integer2 >> 2;
        BlockPos fk15 = null;
        int integer12 = 0;
        for (int integer13 = 0; integer13 < integer10; ++integer13) {
            for (int integer14 = 0; integer14 < integer9; ++integer14) {
                final int integer15 = integer5 + integer14;
                final int integer16 = integer6 + integer13;
                if (list.contains(this.getNoiseBiome(integer15, integer11, integer16))) {
                    if (fk15 == null || random.nextInt(integer12 + 1) == 0) {
                        fk15 = new BlockPos(integer15 << 2, integer2, integer16 << 2);
                    }
                    ++integer12;
                }
            }
        }
        return fk15;
    }
    
    public float getHeightValue(final int integer1, final int integer2) {
        return 0.0f;
    }
    
    public boolean canGenerateStructure(final StructureFeature<?> cfl) {
        return this.supportedStructures.computeIfAbsent(cfl, cfl -> this.possibleBiomes.stream().anyMatch(bkt -> bkt.<FeatureConfiguration>isValidStart(cfl)));
    }
    
    public Set<BlockState> getSurfaceBlocks() {
        if (this.surfaceBlocks.isEmpty()) {
            for (final Biome bkt3 : this.possibleBiomes) {
                this.surfaceBlocks.add(bkt3.getSurfaceBuilderConfig().getTopMaterial());
            }
        }
        return this.surfaceBlocks;
    }
    
    static {
        PLAYER_SPAWN_BIOMES = Lists.<Biome>newArrayList(Biomes.FOREST, Biomes.PLAINS, Biomes.TAIGA, Biomes.TAIGA_HILLS, Biomes.WOODED_HILLS, Biomes.JUNGLE, Biomes.JUNGLE_HILLS);
    }
}
