"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadFromDisk = void 0;
const jsonHelpers_1 = require("../../../../functions/jsonHelpers");
const log_1 = require("../../../../functions/log");
const merge_1 = require("../../../../functions/merge");
const table_1 = require("../../../../functions/table");
const types_1 = require("../../../../functions/types");
const constants_1 = require("./constants");
const DEFAULT_MOD_DATA = "{}";
function loadFromDisk(mod, oldSaveData, classConstructors) {
    if (!mod.HasData()) {
        // There is no "save#.dat" file for this save slot.
        return;
    }
    // First, read the "save#.dat" file into a Lua table.
    const jsonString = readSaveDatFile(mod);
    const newSaveData = (0, jsonHelpers_1.jsonDecode)(jsonString);
    if (constants_1.SAVE_DATA_MANAGER_DEBUG) {
        (0, log_1.log)('Converted data from the "save#.dat" to a Lua table.');
    }
    // Second, iterate over all the fields of the new table.)
    (0, table_1.iterateTableInOrder)(newSaveData, (subscriberName, saveData) => {
        // All elements of loaded save data should have keys that are strings equal to the name of the
        // subscriber/feature. Ignore elements with other types of keys.
        if (!(0, types_1.isString)(subscriberName)) {
            return;
        }
        // All elements of loaded save data should be tables that contain fields corresponding to the
        // `SaveData` interface. Ignore elements that are not tables.
        if (!(0, types_1.isTable)(saveData)) {
            return;
        }
        // Ignore elements that represent subscriptions that no longer exist in the current save data.
        const oldSaveDataForSubscriber = oldSaveData.get(subscriberName);
        if (oldSaveDataForSubscriber === undefined) {
            return;
        }
        if (constants_1.SAVE_DATA_MANAGER_DEBUG) {
            (0, log_1.log)(`Merging in stored data for feature: ${subscriberName}`);
        }
        // We do not want to blow away the child tables of the existing map, because save data could
        // contain out-of-date fields. Instead, merge it one field at a time in a recursive way (and
        // convert Lua tables back to TypeScriptToLua Maps, if necessary).
        (0, merge_1.merge)(oldSaveDataForSubscriber, saveData, subscriberName, classConstructors);
    }, constants_1.SAVE_DATA_MANAGER_DEBUG);
    (0, log_1.log)(`The save data manager loaded data from the "save#.dat" file for mod: ${mod.Name}`);
}
exports.loadFromDisk = loadFromDisk;
function readSaveDatFile(mod) {
    const renderFrameCount = Isaac.GetFrameCount();
    const [ok, jsonStringOrErrMsg] = pcall(tryLoadModData, mod);
    if (!ok) {
        (0, log_1.logError)(`Failed to read from the "save#.dat" file on render frame ${renderFrameCount}: ${jsonStringOrErrMsg}`);
        return DEFAULT_MOD_DATA;
    }
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
    if (jsonStringOrErrMsg === undefined) {
        return DEFAULT_MOD_DATA;
    }
    const jsonStringTrimmed = jsonStringOrErrMsg.trim();
    if (jsonStringTrimmed === "") {
        return DEFAULT_MOD_DATA;
    }
    return jsonStringTrimmed;
}
function tryLoadModData(mod) {
    return mod.LoadData();
}
