package net.minecraft.world.level.dimension;

import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableList;
import net.minecraft.resources.ResourceLocation;
import com.mojang.datafixers.kinds.Applicative;
import java.util.function.Function;
import com.mojang.datafixers.kinds.App;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.List;
import net.minecraft.world.level.biome.TheEndBiomeSource;
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.Map;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Registry;
import net.minecraft.core.MappedRegistry;
import net.minecraft.world.level.chunk.ChunkGenerator;
import java.util.function.Supplier;
import java.util.LinkedHashSet;
import net.minecraft.resources.ResourceKey;
import com.mojang.serialization.MapCodec;

public final class LevelStem {
    public static final MapCodec<LevelStem> CODEC;
    public static final ResourceKey<LevelStem> OVERWORLD;
    public static final ResourceKey<LevelStem> NETHER;
    public static final ResourceKey<LevelStem> END;
    private static final LinkedHashSet<ResourceKey<LevelStem>> BUILTIN_ORDER;
    private final Supplier<DimensionType> type;
    private final ChunkGenerator generator;
    
    public LevelStem(final Supplier<DimensionType> supplier, final ChunkGenerator cha) {
        this.type = supplier;
        this.generator = cha;
    }
    
    public Supplier<DimensionType> typeSupplier() {
        return this.type;
    }
    
    public DimensionType type() {
        return this.type.get();
    }
    
    public ChunkGenerator generator() {
        return this.generator;
    }
    
    public static MappedRegistry<LevelStem> sortMap(final MappedRegistry<LevelStem> gh) {
        final MappedRegistry<LevelStem> gh2 = new MappedRegistry<LevelStem>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental());
        for (final ResourceKey<LevelStem> ug4 : LevelStem.BUILTIN_ORDER) {
            final LevelStem cig5 = gh.get(ug4);
            if (cig5 != null) {
                gh2.<LevelStem>register(ug4, cig5);
                if (!gh.persistent(ug4)) {
                    continue;
                }
                gh2.setPersistent(ug4);
            }
        }
        for (final Map.Entry<ResourceKey<LevelStem>, LevelStem> entry4 : gh.entrySet()) {
            final ResourceKey<LevelStem> ug5 = entry4.getKey();
            if (LevelStem.BUILTIN_ORDER.contains(ug5)) {
                continue;
            }
            gh2.<LevelStem>register(ug5, entry4.getValue());
            if (!gh.persistent(ug5)) {
                continue;
            }
            gh2.setPersistent(ug5);
        }
        return gh2;
    }
    
    public static boolean stable(final long long1, final MappedRegistry<LevelStem> gh) {
        final List<Map.Entry<ResourceKey<LevelStem>, LevelStem>> list4 = Lists.newArrayList(gh.entrySet());
        if (list4.size() != LevelStem.BUILTIN_ORDER.size()) {
            return false;
        }
        final Map.Entry<ResourceKey<LevelStem>, LevelStem> entry5 = list4.get(0);
        final Map.Entry<ResourceKey<LevelStem>, LevelStem> entry6 = list4.get(1);
        final Map.Entry<ResourceKey<LevelStem>, LevelStem> entry7 = list4.get(2);
        if (entry5.getKey() != LevelStem.OVERWORLD || entry6.getKey() != LevelStem.NETHER || entry7.getKey() != LevelStem.END) {
            return false;
        }
        if (entry5.getValue().type() != DimensionType.DEFAULT_OVERWORLD && entry5.getValue().type() != DimensionType.DEFAULT_OVERWORLD_CAVES) {
            return false;
        }
        if (entry6.getValue().type() != DimensionType.DEFAULT_NETHER) {
            return false;
        }
        if (entry7.getValue().type() != DimensionType.DEFAULT_END) {
            return false;
        }
        if (!(entry6.getValue().generator() instanceof NoiseBasedChunkGenerator) || !(entry7.getValue().generator() instanceof NoiseBasedChunkGenerator)) {
            return false;
        }
        final NoiseBasedChunkGenerator cip8 = (NoiseBasedChunkGenerator)entry6.getValue().generator();
        final NoiseBasedChunkGenerator cip9 = (NoiseBasedChunkGenerator)entry7.getValue().generator();
        if (!cip8.stable(long1, NoiseGeneratorSettings.Preset.NETHER)) {
            return false;
        }
        if (!cip9.stable(long1, NoiseGeneratorSettings.Preset.END)) {
            return false;
        }
        if (!(cip8.getBiomeSource() instanceof MultiNoiseBiomeSource)) {
            return false;
        }
        final MultiNoiseBiomeSource btc10 = (MultiNoiseBiomeSource)cip8.getBiomeSource();
        if (!btc10.stable(long1)) {
            return false;
        }
        if (!(cip9.getBiomeSource() instanceof TheEndBiomeSource)) {
            return false;
        }
        final TheEndBiomeSource buh11 = (TheEndBiomeSource)cip9.getBiomeSource();
        return buh11.stable(long1);
    }
    
    static {
        CODEC = RecordCodecBuilder.mapCodec(instance -> ((RecordCodecBuilder.Instance)instance).group((App)DimensionType.CODEC.fieldOf("type").forGetter((Function)LevelStem::typeSupplier), (App)ChunkGenerator.CODEC.fieldOf("generator").forGetter((Function)LevelStem::generator)).apply(instance, ((RecordCodecBuilder.Instance)instance).stable(LevelStem::new)));
        OVERWORLD = ResourceKey.<LevelStem>create(Registry.LEVEL_STEM_REGISTRY, new ResourceLocation("overworld"));
        NETHER = ResourceKey.<LevelStem>create(Registry.LEVEL_STEM_REGISTRY, new ResourceLocation("the_nether"));
        END = ResourceKey.<LevelStem>create(Registry.LEVEL_STEM_REGISTRY, new ResourceLocation("the_end"));
        BUILTIN_ORDER = Sets.<ResourceKey<LevelStem>>newLinkedHashSet(ImmutableList.<ResourceKey<LevelStem>>of(LevelStem.OVERWORLD, LevelStem.NETHER, LevelStem.END));
    }
}
