package net.minecraft.world.level.levelgen;

import com.mojang.serialization.DataResult;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.feature.configurations.StrongholdConfiguration;
import net.minecraft.world.level.levelgen.feature.configurations.StructureFeatureConfiguration;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import com.google.common.collect.Maps;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import java.util.Map;
import com.mojang.datafixers.kinds.Applicative;
import net.minecraft.util.Codecs;
import com.mojang.datafixers.kinds.App;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.function.Function;
import com.mojang.datafixers.util.Either;
import java.util.Objects;
import java.util.Optional;
import net.minecraft.world.level.block.state.BlockState;
import com.mojang.serialization.Codec;

public final class NoiseGeneratorSettings {
    public static final Codec<NoiseGeneratorSettings> DIRECT_CODEC;
    public static final Codec<NoiseGeneratorSettings> CODEC;
    private final StructureSettings structureSettings;
    private final NoiseSettings noiseSettings;
    private final BlockState defaultBlock;
    private final BlockState defaultFluid;
    private final int bedrockRoofPosition;
    private final int bedrockFloorPosition;
    private final int seaLevel;
    private final boolean disableMobGeneration;
    private final Optional<Preset> preset;
    
    private NoiseGeneratorSettings(final StructureSettings ciw, final NoiseSettings cis, final BlockState cfj3, final BlockState cfj4, final int integer5, final int integer6, final int integer7, final boolean boolean8) {
        this(ciw, cis, cfj3, cfj4, integer5, integer6, integer7, boolean8, Optional.<Preset>empty());
    }
    
    private NoiseGeneratorSettings(final StructureSettings ciw, final NoiseSettings cis, final BlockState cfj3, final BlockState cfj4, final int integer5, final int integer6, final int integer7, final boolean boolean8, final Optional<Preset> optional) {
        this.structureSettings = ciw;
        this.noiseSettings = cis;
        this.defaultBlock = cfj3;
        this.defaultFluid = cfj4;
        this.bedrockRoofPosition = integer5;
        this.bedrockFloorPosition = integer6;
        this.seaLevel = integer7;
        this.disableMobGeneration = boolean8;
        this.preset = optional;
    }
    
    public StructureSettings structureSettings() {
        return this.structureSettings;
    }
    
    public NoiseSettings noiseSettings() {
        return this.noiseSettings;
    }
    
    public BlockState getDefaultBlock() {
        return this.defaultBlock;
    }
    
    public BlockState getDefaultFluid() {
        return this.defaultFluid;
    }
    
    public int getBedrockRoofPosition() {
        return this.bedrockRoofPosition;
    }
    
    public int getBedrockFloorPosition() {
        return this.bedrockFloorPosition;
    }
    
    public int seaLevel() {
        return this.seaLevel;
    }
    
    @Deprecated
    protected boolean disableMobGeneration() {
        return this.disableMobGeneration;
    }
    
    public boolean stable(final Preset a) {
        return Objects.equals(this.preset, Optional.<Preset>of(a));
    }
    
    static {
        DIRECT_CODEC = RecordCodecBuilder.create(instance -> ((RecordCodecBuilder.Instance)instance).group((App)StructureSettings.CODEC.fieldOf("structures").forGetter((Function)NoiseGeneratorSettings::structureSettings), (App)NoiseSettings.CODEC.fieldOf("noise").forGetter((Function)NoiseGeneratorSettings::noiseSettings), (App)BlockState.CODEC.fieldOf("default_block").forGetter((Function)NoiseGeneratorSettings::getDefaultBlock), (App)BlockState.CODEC.fieldOf("default_fluid").forGetter((Function)NoiseGeneratorSettings::getDefaultFluid), (App)Codecs.intRange(-20, 276).fieldOf("bedrock_roof_position").forGetter((Function)NoiseGeneratorSettings::getBedrockRoofPosition), (App)Codecs.intRange(-20, 276).fieldOf("bedrock_floor_position").forGetter((Function)NoiseGeneratorSettings::getBedrockFloorPosition), (App)Codecs.intRange(0, 255).fieldOf("sea_level").forGetter((Function)NoiseGeneratorSettings::seaLevel), (App)Codec.BOOL.fieldOf("disable_mob_generation").forGetter((Function)NoiseGeneratorSettings::disableMobGeneration)).apply(instance, NoiseGeneratorSettings::new));
        CODEC = Codec.either((Codec)Preset.CODEC, (Codec)NoiseGeneratorSettings.DIRECT_CODEC).xmap(either -> (NoiseGeneratorSettings)either.map((Function)Preset::settings, (Function)Function.identity()), ciq -> ciq.preset.map(Either::left).orElseGet(() -> Either.right(ciq)));
    }
    
    public static class Preset {
        private static final Map<ResourceLocation, Preset> BY_NAME;
        public static final Codec<Preset> CODEC;
        public static final Preset OVERWORLD;
        public static final Preset AMPLIFIED;
        public static final Preset NETHER;
        public static final Preset END;
        public static final Preset CAVES;
        public static final Preset FLOATING_ISLANDS;
        private final Component description;
        private final ResourceLocation name;
        private final NoiseGeneratorSettings settings;
        
        public Preset(final String string, final Function<Preset, NoiseGeneratorSettings> function) {
            this.name = new ResourceLocation(string);
            this.description = new TranslatableComponent("generator.noise." + string);
            this.settings = function.apply(this);
            Preset.BY_NAME.put(this.name, this);
        }
        
        public NoiseGeneratorSettings settings() {
            return this.settings;
        }
        
        private static NoiseGeneratorSettings end(final StructureSettings ciw, final BlockState cfj2, final BlockState cfj3, final Preset a, final boolean boolean5, final boolean boolean6) {
            return new NoiseGeneratorSettings(ciw, new NoiseSettings(128, new NoiseSamplingSettings(2.0, 1.0, 80.0, 160.0), new NoiseSlideSettings(-3000, 64, -46), new NoiseSlideSettings(-30, 7, 1), 2, 1, 0.0, 0.0, true, false, boolean6, false), cfj2, cfj3, -10, -10, 0, boolean5, Optional.<Preset>of(a), null);
        }
        
        private static NoiseGeneratorSettings nether(final StructureSettings ciw, final BlockState cfj2, final BlockState cfj3, final Preset a) {
            final Map<StructureFeature<?>, StructureFeatureConfiguration> map5 = Maps.newHashMap(StructureSettings.DEFAULTS);
            map5.put(StructureFeature.RUINED_PORTAL, new StructureFeatureConfiguration(25, 10, 34222645));
            return new NoiseGeneratorSettings(new StructureSettings(Optional.<StrongholdConfiguration>ofNullable(ciw.stronghold()), map5), new NoiseSettings(128, new NoiseSamplingSettings(1.0, 3.0, 80.0, 60.0), new NoiseSlideSettings(120, 3, 0), new NoiseSlideSettings(320, 4, -1), 1, 2, 0.0, 0.019921875, false, false, false, false), cfj2, cfj3, 0, 0, 32, false, Optional.<Preset>of(a), null);
        }
        
        private static NoiseGeneratorSettings overworld(final StructureSettings ciw, final boolean boolean2, final Preset a) {
            final double double4 = 0.9999999814507745;
            return new NoiseGeneratorSettings(ciw, new NoiseSettings(256, new NoiseSamplingSettings(0.9999999814507745, 0.9999999814507745, 80.0, 160.0), new NoiseSlideSettings(-10, 3, 0), new NoiseSlideSettings(-30, 0, 0), 1, 2, 1.0, -0.46875, true, true, false, boolean2), Blocks.STONE.defaultBlockState(), Blocks.WATER.defaultBlockState(), -10, 0, 63, false, Optional.<Preset>of(a), null);
        }
        
        static {
            BY_NAME = Maps.newHashMap();
            CODEC = ResourceLocation.CODEC.flatXmap(uh -> Optional.<Preset>ofNullable(Preset.BY_NAME.get(uh)).map(DataResult::success).orElseGet(() -> DataResult.error("Unknown preset: " + uh)), a -> DataResult.success(a.name)).stable();
            OVERWORLD = new Preset("overworld", a -> overworld(new StructureSettings(true), false, a));
            AMPLIFIED = new Preset("amplified", a -> overworld(new StructureSettings(true), true, a));
            NETHER = new Preset("nether", a -> nether(new StructureSettings(false), Blocks.NETHERRACK.defaultBlockState(), Blocks.LAVA.defaultBlockState(), a));
            END = new Preset("end", a -> end(new StructureSettings(false), Blocks.END_STONE.defaultBlockState(), Blocks.AIR.defaultBlockState(), a, true, true));
            CAVES = new Preset("caves", a -> nether(new StructureSettings(false), Blocks.STONE.defaultBlockState(), Blocks.WATER.defaultBlockState(), a));
            FLOATING_ISLANDS = new Preset("floating_islands", a -> end(new StructureSettings(false), Blocks.STONE.defaultBlockState(), Blocks.WATER.defaultBlockState(), a, false, false));
        }
    }
}
