package net.minecraft.world.level.storage;

import org.apache.logging.log4j.LogManager;
import java.util.Collection;
import com.google.common.collect.ImmutableSet;
import net.minecraft.CrashReportCategory;
import net.minecraft.world.Difficulty;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.GameType;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.util.datafix.DataFixTypes;
import net.minecraft.world.level.DataPackConfig;
import com.mojang.serialization.DynamicOps;
import net.minecraft.resources.RegistryWriteOps;
import net.minecraft.nbt.NbtOps;
import java.util.function.Consumer;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.core.RegistryAccess;
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.Optional;
import net.minecraft.Util;
import com.mojang.serialization.Decoder;
import net.minecraft.core.SerializableUUID;
import com.mojang.serialization.DynamicLike;
import java.util.function.Function;
import net.minecraft.nbt.Tag;
import com.mojang.serialization.Dynamic;
import net.minecraft.world.level.timers.TimerCallbacks;
import com.google.common.collect.Sets;
import net.minecraft.SharedConstants;
import java.util.LinkedHashSet;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.timers.TimerQueue;
import java.util.Set;
import java.util.UUID;
import net.minecraft.world.level.border.WorldBorder;
import net.minecraft.nbt.CompoundTag;
import javax.annotation.Nullable;
import com.mojang.datafixers.DataFixer;
import com.mojang.serialization.Lifecycle;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.LevelSettings;
import org.apache.logging.log4j.Logger;

public class PrimaryLevelData implements ServerLevelData, WorldData {
    private static final Logger LOGGER;
    private LevelSettings settings;
    private final WorldGenSettings worldGenSettings;
    private final Lifecycle worldGenSettingsLifecycle;
    private int xSpawn;
    private int ySpawn;
    private int zSpawn;
    private long gameTime;
    private long dayTime;
    @Nullable
    private final DataFixer fixerUpper;
    private final int playerDataVersion;
    private boolean upgradedPlayerTag;
    @Nullable
    private CompoundTag loadedPlayerTag;
    private final int version;
    private int clearWeatherTime;
    private boolean raining;
    private int rainTime;
    private boolean thundering;
    private int thunderTime;
    private boolean initialized;
    private boolean difficultyLocked;
    private WorldBorder.Settings worldBorder;
    private CompoundTag endDragonFightData;
    @Nullable
    private CompoundTag customBossEvents;
    private int wanderingTraderSpawnDelay;
    private int wanderingTraderSpawnChance;
    @Nullable
    private UUID wanderingTraderId;
    private final Set<String> knownServerBrands;
    private boolean wasModded;
    private final TimerQueue<MinecraftServer> scheduledEvents;
    
    private PrimaryLevelData(@Nullable final DataFixer dataFixer, final int integer2, @Nullable final CompoundTag le3, final boolean boolean4, final int integer5, final int integer6, final int integer7, final long long8, final long long9, final int integer10, final int integer11, final int integer12, final boolean boolean13, final int integer14, final boolean boolean15, final boolean boolean16, final boolean boolean17, final WorldBorder.Settings c, final int integer19, final int integer20, @Nullable final UUID uUID, final LinkedHashSet<String> linkedHashSet, final TimerQueue<MinecraftServer> ded, @Nullable final CompoundTag le24, final CompoundTag le25, final LevelSettings bqe, final WorldGenSettings cix, final Lifecycle lifecycle) {
        this.fixerUpper = dataFixer;
        this.wasModded = boolean4;
        this.xSpawn = integer5;
        this.ySpawn = integer6;
        this.zSpawn = integer7;
        this.gameTime = long8;
        this.dayTime = long9;
        this.version = integer10;
        this.clearWeatherTime = integer11;
        this.rainTime = integer12;
        this.raining = boolean13;
        this.thunderTime = integer14;
        this.thundering = boolean15;
        this.initialized = boolean16;
        this.difficultyLocked = boolean17;
        this.worldBorder = c;
        this.wanderingTraderSpawnDelay = integer19;
        this.wanderingTraderSpawnChance = integer20;
        this.wanderingTraderId = uUID;
        this.knownServerBrands = linkedHashSet;
        this.loadedPlayerTag = le3;
        this.playerDataVersion = integer2;
        this.scheduledEvents = ded;
        this.customBossEvents = le24;
        this.endDragonFightData = le25;
        this.settings = bqe;
        this.worldGenSettings = cix;
        this.worldGenSettingsLifecycle = lifecycle;
    }
    
    public PrimaryLevelData(final LevelSettings bqe, final WorldGenSettings cix, final Lifecycle lifecycle) {
        this(null, SharedConstants.getCurrentVersion().getWorldVersion(), null, false, 0, 0, 0, 0L, 0L, 19133, 0, 0, false, 0, false, false, false, WorldBorder.DEFAULT_SETTINGS, 0, 0, null, Sets.<String>newLinkedHashSet(), new TimerQueue<MinecraftServer>(TimerCallbacks.SERVER_CALLBACKS), null, new CompoundTag(), bqe.copy(), cix, lifecycle);
    }
    
    public static PrimaryLevelData parse(final Dynamic<Tag> dynamic, final DataFixer dataFixer, final int integer, @Nullable final CompoundTag le, final LevelSettings bqe, final LevelVersion dag, final WorldGenSettings cix, final Lifecycle lifecycle) {
        final long long9 = dynamic.get("Time").asLong(0L);
        final CompoundTag le2 = dynamic.get("DragonFight").result().<CompoundTag>map(Dynamic::getValue).orElseGet(() -> (Tag)dynamic.get("DimensionData").get("1").get("DragonFight").orElseEmptyMap().getValue());
        return new PrimaryLevelData(dataFixer, integer, le, dynamic.get("WasModded").asBoolean(false), dynamic.get("SpawnX").asInt(0), dynamic.get("SpawnY").asInt(0), dynamic.get("SpawnZ").asInt(0), long9, dynamic.get("DayTime").asLong(long9), dag.levelDataVersion(), dynamic.get("clearWeatherTime").asInt(0), dynamic.get("rainTime").asInt(0), dynamic.get("raining").asBoolean(false), dynamic.get("thunderTime").asInt(0), dynamic.get("thundering").asBoolean(false), dynamic.get("initialized").asBoolean(true), dynamic.get("DifficultyLocked").asBoolean(false), WorldBorder.Settings.read(dynamic, WorldBorder.DEFAULT_SETTINGS), dynamic.get("WanderingTraderSpawnDelay").asInt(0), dynamic.get("WanderingTraderSpawnChance").asInt(0), dynamic.get("WanderingTraderId").read((Decoder)SerializableUUID.CODEC).result().orElse(null), dynamic.get("ServerBrands").asStream().flatMap(dynamic -> Util.toStream(dynamic.asString().result())).collect(Collectors.toCollection(Sets::newLinkedHashSet)), new TimerQueue<MinecraftServer>(TimerCallbacks.SERVER_CALLBACKS, dynamic.get("ScheduledEvents").asStream()), (CompoundTag)dynamic.get("CustomBossEvents").orElseEmptyMap().getValue(), le2, bqe, cix, lifecycle);
    }
    
    @Override
    public CompoundTag createTag(final RegistryAccess gm, @Nullable CompoundTag le) {
        this.updatePlayerTag();
        if (le == null) {
            le = this.loadedPlayerTag;
        }
        final CompoundTag le2 = new CompoundTag();
        this.setTagData(gm, le2, le);
        return le2;
    }
    
    private void setTagData(final RegistryAccess gm, final CompoundTag le2, @Nullable final CompoundTag le3) {
        final ListTag lk5 = new ListTag();
        this.knownServerBrands.stream().map(StringTag::valueOf).forEach(lk5::add);
        le2.put("ServerBrands", lk5);
        le2.putBoolean("WasModded", this.wasModded);
        final CompoundTag le4 = new CompoundTag();
        le4.putString("Name", SharedConstants.getCurrentVersion().getName());
        le4.putInt("Id", SharedConstants.getCurrentVersion().getWorldVersion());
        le4.putBoolean("Snapshot", !SharedConstants.getCurrentVersion().isStable());
        le2.put("Version", le4);
        le2.putInt("DataVersion", SharedConstants.getCurrentVersion().getWorldVersion());
        final RegistryWriteOps<Tag> uf7 = RegistryWriteOps.<Tag>create((com.mojang.serialization.DynamicOps<Tag>)NbtOps.INSTANCE, gm);
        WorldGenSettings.CODEC.encodeStart((DynamicOps)uf7, this.worldGenSettings).resultOrPartial((Consumer)Util.prefix("WorldGenSettings: ", PrimaryLevelData.LOGGER::error)).ifPresent(lu -> le2.put("WorldGenSettings", lu));
        le2.putInt("GameType", this.settings.gameType().getId());
        le2.putInt("SpawnX", this.xSpawn);
        le2.putInt("SpawnY", this.ySpawn);
        le2.putInt("SpawnZ", this.zSpawn);
        le2.putLong("Time", this.gameTime);
        le2.putLong("DayTime", this.dayTime);
        le2.putLong("LastPlayed", Util.getEpochMillis());
        le2.putString("LevelName", this.settings.levelName());
        le2.putInt("version", 19133);
        le2.putInt("clearWeatherTime", this.clearWeatherTime);
        le2.putInt("rainTime", this.rainTime);
        le2.putBoolean("raining", this.raining);
        le2.putInt("thunderTime", this.thunderTime);
        le2.putBoolean("thundering", this.thundering);
        le2.putBoolean("hardcore", this.settings.hardcore());
        le2.putBoolean("allowCommands", this.settings.allowCommands());
        le2.putBoolean("initialized", this.initialized);
        this.worldBorder.write(le2);
        le2.putByte("Difficulty", (byte)this.settings.difficulty().getId());
        le2.putBoolean("DifficultyLocked", this.difficultyLocked);
        le2.put("GameRules", this.settings.gameRules().createTag());
        le2.put("DragonFight", this.endDragonFightData);
        if (le3 != null) {
            le2.put("Player", le3);
        }
        DataPackConfig.CODEC.encodeStart((DynamicOps)NbtOps.INSTANCE, this.settings.getDataPackConfig()).result().ifPresent(lu -> le2.put("DataPacks", lu));
        if (this.customBossEvents != null) {
            le2.put("CustomBossEvents", this.customBossEvents);
        }
        le2.put("ScheduledEvents", this.scheduledEvents.store());
        le2.putInt("WanderingTraderSpawnDelay", this.wanderingTraderSpawnDelay);
        le2.putInt("WanderingTraderSpawnChance", this.wanderingTraderSpawnChance);
        if (this.wanderingTraderId != null) {
            le2.putUUID("WanderingTraderId", this.wanderingTraderId);
        }
    }
    
    @Override
    public int getXSpawn() {
        return this.xSpawn;
    }
    
    @Override
    public int getYSpawn() {
        return this.ySpawn;
    }
    
    @Override
    public int getZSpawn() {
        return this.zSpawn;
    }
    
    @Override
    public long getGameTime() {
        return this.gameTime;
    }
    
    @Override
    public long getDayTime() {
        return this.dayTime;
    }
    
    private void updatePlayerTag() {
        if (this.upgradedPlayerTag || this.loadedPlayerTag == null) {
            return;
        }
        if (this.playerDataVersion < SharedConstants.getCurrentVersion().getWorldVersion()) {
            if (this.fixerUpper == null) {
                throw Util.<NullPointerException>pauseInIde(new NullPointerException("Fixer Upper not set inside LevelData, and the player tag is not upgraded."));
            }
            this.loadedPlayerTag = NbtUtils.update(this.fixerUpper, DataFixTypes.PLAYER, this.loadedPlayerTag, this.playerDataVersion);
        }
        this.upgradedPlayerTag = true;
    }
    
    @Override
    public CompoundTag getLoadedPlayerTag() {
        this.updatePlayerTag();
        return this.loadedPlayerTag;
    }
    
    @Override
    public void setXSpawn(final int integer) {
        this.xSpawn = integer;
    }
    
    @Override
    public void setYSpawn(final int integer) {
        this.ySpawn = integer;
    }
    
    @Override
    public void setZSpawn(final int integer) {
        this.zSpawn = integer;
    }
    
    @Override
    public void setGameTime(final long long1) {
        this.gameTime = long1;
    }
    
    @Override
    public void setDayTime(final long long1) {
        this.dayTime = long1;
    }
    
    @Override
    public void setSpawn(final BlockPos fu) {
        this.xSpawn = fu.getX();
        this.ySpawn = fu.getY();
        this.zSpawn = fu.getZ();
    }
    
    @Override
    public String getLevelName() {
        return this.settings.levelName();
    }
    
    @Override
    public int getVersion() {
        return this.version;
    }
    
    @Override
    public int getClearWeatherTime() {
        return this.clearWeatherTime;
    }
    
    @Override
    public void setClearWeatherTime(final int integer) {
        this.clearWeatherTime = integer;
    }
    
    @Override
    public boolean isThundering() {
        return this.thundering;
    }
    
    @Override
    public void setThundering(final boolean boolean1) {
        this.thundering = boolean1;
    }
    
    @Override
    public int getThunderTime() {
        return this.thunderTime;
    }
    
    @Override
    public void setThunderTime(final int integer) {
        this.thunderTime = integer;
    }
    
    @Override
    public boolean isRaining() {
        return this.raining;
    }
    
    @Override
    public void setRaining(final boolean boolean1) {
        this.raining = boolean1;
    }
    
    @Override
    public int getRainTime() {
        return this.rainTime;
    }
    
    @Override
    public void setRainTime(final int integer) {
        this.rainTime = integer;
    }
    
    @Override
    public GameType getGameType() {
        return this.settings.gameType();
    }
    
    @Override
    public void setGameType(final GameType bpy) {
        this.settings = this.settings.withGameType(bpy);
    }
    
    @Override
    public boolean isHardcore() {
        return this.settings.hardcore();
    }
    
    @Override
    public boolean getAllowCommands() {
        return this.settings.allowCommands();
    }
    
    @Override
    public boolean isInitialized() {
        return this.initialized;
    }
    
    @Override
    public void setInitialized(final boolean boolean1) {
        this.initialized = boolean1;
    }
    
    @Override
    public GameRules getGameRules() {
        return this.settings.gameRules();
    }
    
    @Override
    public WorldBorder.Settings getWorldBorder() {
        return this.worldBorder;
    }
    
    @Override
    public void setWorldBorder(final WorldBorder.Settings c) {
        this.worldBorder = c;
    }
    
    @Override
    public Difficulty getDifficulty() {
        return this.settings.difficulty();
    }
    
    @Override
    public void setDifficulty(final Difficulty and) {
        this.settings = this.settings.withDifficulty(and);
    }
    
    @Override
    public boolean isDifficultyLocked() {
        return this.difficultyLocked;
    }
    
    @Override
    public void setDifficultyLocked(final boolean boolean1) {
        this.difficultyLocked = boolean1;
    }
    
    @Override
    public TimerQueue<MinecraftServer> getScheduledEvents() {
        return this.scheduledEvents;
    }
    
    @Override
    public void fillCrashReportCategory(final CrashReportCategory k) {
        super.fillCrashReportCategory(k);
        super.fillCrashReportCategory(k);
    }
    
    @Override
    public WorldGenSettings worldGenSettings() {
        return this.worldGenSettings;
    }
    
    @Override
    public Lifecycle worldGenSettingsLifecycle() {
        return this.worldGenSettingsLifecycle;
    }
    
    @Override
    public CompoundTag endDragonFightData() {
        return this.endDragonFightData;
    }
    
    @Override
    public void setEndDragonFightData(final CompoundTag le) {
        this.endDragonFightData = le;
    }
    
    @Override
    public DataPackConfig getDataPackConfig() {
        return this.settings.getDataPackConfig();
    }
    
    @Override
    public void setDataPackConfig(final DataPackConfig bpn) {
        this.settings = this.settings.withDataPackConfig(bpn);
    }
    
    @Nullable
    @Override
    public CompoundTag getCustomBossEvents() {
        return this.customBossEvents;
    }
    
    @Override
    public void setCustomBossEvents(@Nullable final CompoundTag le) {
        this.customBossEvents = le;
    }
    
    @Override
    public int getWanderingTraderSpawnDelay() {
        return this.wanderingTraderSpawnDelay;
    }
    
    @Override
    public void setWanderingTraderSpawnDelay(final int integer) {
        this.wanderingTraderSpawnDelay = integer;
    }
    
    @Override
    public int getWanderingTraderSpawnChance() {
        return this.wanderingTraderSpawnChance;
    }
    
    @Override
    public void setWanderingTraderSpawnChance(final int integer) {
        this.wanderingTraderSpawnChance = integer;
    }
    
    @Override
    public void setWanderingTraderId(final UUID uUID) {
        this.wanderingTraderId = uUID;
    }
    
    @Override
    public void setModdedInfo(final String string, final boolean boolean2) {
        this.knownServerBrands.add(string);
        this.wasModded |= boolean2;
    }
    
    @Override
    public boolean wasModded() {
        return this.wasModded;
    }
    
    @Override
    public Set<String> getKnownServerBrands() {
        return ImmutableSet.copyOf(this.knownServerBrands);
    }
    
    @Override
    public ServerLevelData overworldData() {
        return this;
    }
    
    @Override
    public LevelSettings getLevelSettings() {
        return this.settings.copy();
    }
    
    static {
        LOGGER = LogManager.getLogger();
    }
}
