package net.minecraft.world.level.dimension;

import net.minecraft.resources.RegistryFileCodec;
import net.minecraft.world.level.biome.FuzzyOffsetConstantColumnBiomeZoomer;
import com.mojang.datafixers.kinds.Applicative;
import net.minecraft.util.Codecs;
import java.util.function.Function;
import com.mojang.datafixers.kinds.App;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.Block;
import net.minecraft.tags.Tag;
import java.io.File;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Registry;
import net.minecraft.core.MappedRegistry;
import net.minecraft.world.level.biome.MultiNoiseBiomeSource;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import net.minecraft.world.level.biome.TheEndBiomeSource;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.core.RegistryAccess;
import java.util.Optional;
import net.minecraft.world.level.Level;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.Dynamic;
import net.minecraft.util.Mth;
import net.minecraft.world.level.biome.FuzzyOffsetBiomeZoomer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.BiomeZoomer;
import java.util.OptionalLong;
import java.util.function.Supplier;
import com.mojang.serialization.Codec;
import net.minecraft.resources.ResourceKey;
import com.mojang.serialization.MapCodec;

public class DimensionType {
    public static final MapCodec<DimensionType> DIRECT_CODEC;
    public static final float[] MOON_BRIGHTNESS_PER_PHASE;
    public static final ResourceKey<DimensionType> OVERWORLD_LOCATION;
    public static final ResourceKey<DimensionType> NETHER_LOCATION;
    public static final ResourceKey<DimensionType> END_LOCATION;
    protected static final DimensionType DEFAULT_OVERWORLD;
    protected static final DimensionType DEFAULT_NETHER;
    protected static final DimensionType DEFAULT_END;
    public static final ResourceKey<DimensionType> OVERWORLD_CAVES_LOCATION;
    protected static final DimensionType DEFAULT_OVERWORLD_CAVES;
    public static final Codec<Supplier<DimensionType>> CODEC;
    private final OptionalLong fixedTime;
    private final boolean hasSkylight;
    private final boolean hasCeiling;
    private final boolean ultraWarm;
    private final boolean natural;
    private final boolean shrunk;
    private final boolean createDragonFight;
    private final boolean piglinSafe;
    private final boolean bedWorks;
    private final boolean respawnAnchorWorks;
    private final boolean hasRaids;
    private final int logicalHeight;
    private final BiomeZoomer biomeZoomer;
    private final ResourceLocation infiniburn;
    private final float ambientLight;
    private final transient float[] brightnessRamp;
    
    public static DimensionType defaultOverworld() {
        return DimensionType.DEFAULT_OVERWORLD;
    }
    
    public static DimensionType defaultOverworldCaves() {
        return DimensionType.DEFAULT_OVERWORLD_CAVES;
    }
    
    protected DimensionType(final OptionalLong optionalLong, final boolean boolean2, final boolean boolean3, final boolean boolean4, final boolean boolean5, final boolean boolean6, final boolean boolean7, final boolean boolean8, final boolean boolean9, final boolean boolean10, final int integer, final ResourceLocation uh, final float float13) {
        this(optionalLong, boolean2, boolean3, boolean4, boolean5, boolean6, false, boolean7, boolean8, boolean9, boolean10, integer, FuzzyOffsetBiomeZoomer.INSTANCE, uh, float13);
    }
    
    protected DimensionType(final OptionalLong optionalLong, final boolean boolean2, final boolean boolean3, final boolean boolean4, final boolean boolean5, final boolean boolean6, final boolean boolean7, final boolean boolean8, final boolean boolean9, final boolean boolean10, final boolean boolean11, final int integer, final BiomeZoomer brj, final ResourceLocation uh, final float float15) {
        this.fixedTime = optionalLong;
        this.hasSkylight = boolean2;
        this.hasCeiling = boolean3;
        this.ultraWarm = boolean4;
        this.natural = boolean5;
        this.shrunk = boolean6;
        this.createDragonFight = boolean7;
        this.piglinSafe = boolean8;
        this.bedWorks = boolean9;
        this.respawnAnchorWorks = boolean10;
        this.hasRaids = boolean11;
        this.logicalHeight = integer;
        this.biomeZoomer = brj;
        this.infiniburn = uh;
        this.ambientLight = float15;
        this.brightnessRamp = fillBrightnessRamp(float15);
    }
    
    private static float[] fillBrightnessRamp(final float float1) {
        final float[] arr2 = new float[16];
        for (int integer3 = 0; integer3 <= 15; ++integer3) {
            final float float2 = integer3 / 15.0f;
            final float float3 = float2 / (4.0f - 3.0f * float2);
            arr2[integer3] = Mth.lerp(float1, float3, 1.0f);
        }
        return arr2;
    }
    
    @Deprecated
    public static DataResult<ResourceKey<Level>> parseLegacy(final Dynamic<?> dynamic) {
        final Optional<Number> optional2 = (Optional<Number>)dynamic.asNumber().result();
        if (optional2.isPresent()) {
            final int integer3 = optional2.get().intValue();
            if (integer3 == -1) {
                return (DataResult<ResourceKey<Level>>)DataResult.success(Level.NETHER);
            }
            if (integer3 == 0) {
                return (DataResult<ResourceKey<Level>>)DataResult.success(Level.OVERWORLD);
            }
            if (integer3 == 1) {
                return (DataResult<ResourceKey<Level>>)DataResult.success(Level.END);
            }
        }
        return (DataResult<ResourceKey<Level>>)Level.RESOURCE_KEY_CODEC.parse((Dynamic)dynamic);
    }
    
    public static RegistryAccess.RegistryHolder registerBuiltin(final RegistryAccess.RegistryHolder a) {
        a.registerDimension(DimensionType.OVERWORLD_LOCATION, DimensionType.DEFAULT_OVERWORLD);
        a.registerDimension(DimensionType.OVERWORLD_CAVES_LOCATION, DimensionType.DEFAULT_OVERWORLD_CAVES);
        a.registerDimension(DimensionType.NETHER_LOCATION, DimensionType.DEFAULT_NETHER);
        a.registerDimension(DimensionType.END_LOCATION, DimensionType.DEFAULT_END);
        return a;
    }
    
    private static ChunkGenerator defaultEndGenerator(final long long1) {
        return new NoiseBasedChunkGenerator(new TheEndBiomeSource(long1), long1, NoiseGeneratorSettings.Preset.END.settings());
    }
    
    private static ChunkGenerator defaultNetherGenerator(final long long1) {
        return new NoiseBasedChunkGenerator(MultiNoiseBiomeSource.Preset.NETHER.biomeSource(long1), long1, NoiseGeneratorSettings.Preset.NETHER.settings());
    }
    
    public static MappedRegistry<LevelStem> defaultDimensions(final long long1) {
        final MappedRegistry<LevelStem> gh3 = new MappedRegistry<LevelStem>(Registry.LEVEL_STEM_REGISTRY, Lifecycle.experimental());
        gh3.<LevelStem>register(LevelStem.NETHER, new LevelStem(() -> DimensionType.DEFAULT_NETHER, defaultNetherGenerator(long1)));
        gh3.<LevelStem>register(LevelStem.END, new LevelStem(() -> DimensionType.DEFAULT_END, defaultEndGenerator(long1)));
        gh3.setPersistent(LevelStem.NETHER);
        gh3.setPersistent(LevelStem.END);
        return gh3;
    }
    
    @Deprecated
    public String getFileSuffix() {
        if (this == DimensionType.DEFAULT_END) {
            return "_end";
        }
        return "";
    }
    
    public static File getStorageFolder(final ResourceKey<Level> ug, final File file) {
        if (ug == Level.OVERWORLD) {
            return file;
        }
        if (ug == Level.END) {
            return new File(file, "DIM1");
        }
        if (ug == Level.NETHER) {
            return new File(file, "DIM-1");
        }
        return new File(file, "dimensions/" + ug.location().getNamespace() + "/" + ug.location().getPath());
    }
    
    public boolean hasSkyLight() {
        return this.hasSkylight;
    }
    
    public boolean hasCeiling() {
        return this.hasCeiling;
    }
    
    public boolean ultraWarm() {
        return this.ultraWarm;
    }
    
    public boolean natural() {
        return this.natural;
    }
    
    public boolean shrunk() {
        return this.shrunk;
    }
    
    public boolean piglinSafe() {
        return this.piglinSafe;
    }
    
    public boolean bedWorks() {
        return this.bedWorks;
    }
    
    public boolean respawnAnchorWorks() {
        return this.respawnAnchorWorks;
    }
    
    public boolean hasRaids() {
        return this.hasRaids;
    }
    
    public int logicalHeight() {
        return this.logicalHeight;
    }
    
    public boolean createDragonFight() {
        return this.createDragonFight;
    }
    
    public BiomeZoomer getBiomeZoomer() {
        return this.biomeZoomer;
    }
    
    public boolean hasFixedTime() {
        return this.fixedTime.isPresent();
    }
    
    public float timeOfDay(final long long1) {
        final double double4 = Mth.frac(this.fixedTime.orElse(long1) / 24000.0 - 0.25);
        final double double5 = 0.5 - Math.cos(double4 * 3.141592653589793) / 2.0;
        return (float)(double4 * 2.0 + double5) / 3.0f;
    }
    
    public int moonPhase(final long long1) {
        return (int)(long1 / 24000L % 8L + 8L) % 8;
    }
    
    public float brightness(final int integer) {
        return this.brightnessRamp[integer];
    }
    
    public Tag<Block> infiniburn() {
        final Tag<Block> adf2 = BlockTags.getAllTags().getTag(this.infiniburn);
        return (adf2 != null) ? adf2 : BlockTags.INFINIBURN_OVERWORLD;
    }
    
    static {
        DIRECT_CODEC = RecordCodecBuilder.mapCodec(instance -> ((RecordCodecBuilder.Instance)instance).group((App)Codec.LONG.optionalFieldOf("fixed_time").xmap(optional -> optional.map(OptionalLong::of).orElseGet(OptionalLong::empty), optionalLong -> optionalLong.isPresent() ? Optional.<Long>of(optionalLong.getAsLong()) : Optional.<Long>empty()).forGetter(cif -> cif.fixedTime), (App)Codec.BOOL.fieldOf("has_skylight").forGetter((Function)DimensionType::hasSkyLight), (App)Codec.BOOL.fieldOf("has_ceiling").forGetter((Function)DimensionType::hasCeiling), (App)Codec.BOOL.fieldOf("ultrawarm").forGetter((Function)DimensionType::ultraWarm), (App)Codec.BOOL.fieldOf("natural").forGetter((Function)DimensionType::natural), (App)Codec.BOOL.fieldOf("shrunk").forGetter((Function)DimensionType::shrunk), (App)Codec.BOOL.fieldOf("piglin_safe").forGetter((Function)DimensionType::piglinSafe), (App)Codec.BOOL.fieldOf("bed_works").forGetter((Function)DimensionType::bedWorks), (App)Codec.BOOL.fieldOf("respawn_anchor_works").forGetter((Function)DimensionType::respawnAnchorWorks), (App)Codec.BOOL.fieldOf("has_raids").forGetter((Function)DimensionType::hasRaids), (App)Codecs.intRange(0, 256).fieldOf("logical_height").forGetter((Function)DimensionType::logicalHeight), (App)ResourceLocation.CODEC.fieldOf("infiniburn").forGetter(cif -> cif.infiniburn), (App)Codec.FLOAT.fieldOf("ambient_light").forGetter(cif -> cif.ambientLight)).apply(instance, DimensionType::new));
        MOON_BRIGHTNESS_PER_PHASE = new float[] { 1.0f, 0.75f, 0.5f, 0.25f, 0.0f, 0.25f, 0.5f, 0.75f };
        OVERWORLD_LOCATION = ResourceKey.<DimensionType>create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation("overworld"));
        NETHER_LOCATION = ResourceKey.<DimensionType>create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation("the_nether"));
        END_LOCATION = ResourceKey.<DimensionType>create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation("the_end"));
        DEFAULT_OVERWORLD = new DimensionType(OptionalLong.empty(), true, false, false, true, false, false, false, true, false, true, 256, FuzzyOffsetConstantColumnBiomeZoomer.INSTANCE, BlockTags.INFINIBURN_OVERWORLD.getName(), 0.0f);
        DEFAULT_NETHER = new DimensionType(OptionalLong.of(18000L), false, true, true, false, true, false, true, false, true, false, 128, FuzzyOffsetBiomeZoomer.INSTANCE, BlockTags.INFINIBURN_NETHER.getName(), 0.1f);
        DEFAULT_END = new DimensionType(OptionalLong.of(6000L), false, false, false, false, false, true, false, false, false, true, 256, FuzzyOffsetBiomeZoomer.INSTANCE, BlockTags.INFINIBURN_END.getName(), 0.0f);
        OVERWORLD_CAVES_LOCATION = ResourceKey.<DimensionType>create(Registry.DIMENSION_TYPE_REGISTRY, new ResourceLocation("overworld_caves"));
        DEFAULT_OVERWORLD_CAVES = new DimensionType(OptionalLong.empty(), true, true, false, true, false, false, false, true, false, true, 256, FuzzyOffsetConstantColumnBiomeZoomer.INSTANCE, BlockTags.INFINIBURN_OVERWORLD.getName(), 0.0f);
        CODEC = (Codec)RegistryFileCodec.<DimensionType>create(Registry.DIMENSION_TYPE_REGISTRY, DimensionType.DIRECT_CODEC);
    }
}
