local ____lualib = require("lualib_bundle")
local __TS__New = ____lualib.__TS__New
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__TypeOf = ____lualib.__TS__TypeOf
local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys
local __TS__DecorateLegacy = ____lualib.__TS__DecorateLegacy
local __TS__ArraySort = ____lualib.__TS__ArraySort
local ____exports = {}
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local CollectibleType = ____isaac_2Dtypescript_2Ddefinitions.CollectibleType
local ModCallback = ____isaac_2Dtypescript_2Ddefinitions.ModCallback
local ____decorators = require("decorators")
local Exported = ____decorators.Exported
local ____ModCallbackCustom = require("enums.ModCallbackCustom")
local ModCallbackCustom = ____ModCallbackCustom.ModCallbackCustom
local ____SaveDataKey = require("enums.SaveDataKey")
local SaveDataKey = ____SaveDataKey.SaveDataKey
local ____SerializationType = require("enums.SerializationType")
local SerializationType = ____SerializationType.SerializationType
local ____deepCopy = require("functions.deepCopy")
local deepCopy = ____deepCopy.deepCopy
local ____frames = require("functions.frames")
local isAfterGameFrame = ____frames.isAfterGameFrame
local ____log = require("functions.log")
local log = ____log.log
local ____stage = require("functions.stage")
local onFirstFloor = ____stage.onFirstFloor
local ____tstlClass = require("functions.tstlClass")
local getTSTLClassName = ____tstlClass.getTSTLClassName
local isTSTLClass = ____tstlClass.isTSTLClass
local ____types = require("functions.types")
local isString = ____types.isString
local isTable = ____types.isTable
local ____utils = require("functions.utils")
local assertDefined = ____utils.assertDefined
local ____ReadonlySet = require("types.ReadonlySet")
local ReadonlySet = ____ReadonlySet.ReadonlySet
local ____Feature = require("classes.private.Feature")
local Feature = ____Feature.Feature
local ____glowingHourGlass = require("classes.features.other.saveDataManager.glowingHourGlass")
local makeGlowingHourGlassBackup = ____glowingHourGlass.makeGlowingHourGlassBackup
local restoreGlowingHourGlassBackup = ____glowingHourGlass.restoreGlowingHourGlassBackup
local ____loadFromDisk = require("classes.features.other.saveDataManager.loadFromDisk")
local loadFromDisk = ____loadFromDisk.loadFromDisk
local ____restoreDefaults = require("classes.features.other.saveDataManager.restoreDefaults")
local restoreDefaultForFeatureKey = ____restoreDefaults.restoreDefaultForFeatureKey
local restoreDefaultsForAllFeaturesAndKeys = ____restoreDefaults.restoreDefaultsForAllFeaturesAndKeys
local restoreDefaultsForAllFeaturesKey = ____restoreDefaults.restoreDefaultsForAllFeaturesKey
local ____saveToDisk = require("classes.features.other.saveDataManager.saveToDisk")
local saveToDisk = ____saveToDisk.saveToDisk
local NON_USER_DEFINED_CLASS_NAMES = __TS__New(ReadonlySet, {"Map", "Set", "DefaultMap"})
____exports.SaveDataManager = __TS__Class()
local SaveDataManager = ____exports.SaveDataManager
SaveDataManager.name = "SaveDataManager"
__TS__ClassExtends(SaveDataManager, Feature)
function SaveDataManager.prototype.____constructor(self, mod)
    Feature.prototype.____constructor(self)
    self.saveDataMap = {}
    self.saveDataDefaultsMap = {}
    self.saveDataConditionalFuncMap = {}
    self.saveDataGlowingHourGlassMap = {}
    self.classConstructors = {}
    self.inARun = false
    self.restoreGlowingHourGlassDataOnNextRoom = false
    self.postUseItemGlowingHourGlass = function(____, _collectibleType, _rng, _player, _useFlags, _activeSlot, _customVarData)
        self.restoreGlowingHourGlassDataOnNextRoom = true
        return nil
    end
    self.postPlayerInit = function(____, _player)
        if self.inARun then
            return
        end
        self.inARun = true
        self.restoreGlowingHourGlassDataOnNextRoom = false
        loadFromDisk(nil, self.mod, self.saveDataMap, self.classConstructors)
        local isContinued = isAfterGameFrame(nil, 0)
        if not isContinued then
            restoreDefaultsForAllFeaturesAndKeys(nil, self.saveDataMap, self.saveDataDefaultsMap)
        end
    end
    self.preGameExit = function()
        saveToDisk(nil, self.mod, self.saveDataMap, self.saveDataConditionalFuncMap)
        self.inARun = false
    end
    self.postNewLevel = function()
        restoreDefaultsForAllFeaturesKey(nil, self.saveDataMap, self.saveDataDefaultsMap, SaveDataKey.LEVEL)
        if not onFirstFloor(nil) then
            saveToDisk(nil, self.mod, self.saveDataMap, self.saveDataConditionalFuncMap)
        end
    end
    self.postNewRoomEarly = function()
        restoreDefaultsForAllFeaturesKey(nil, self.saveDataMap, self.saveDataDefaultsMap, SaveDataKey.ROOM)
        if self.restoreGlowingHourGlassDataOnNextRoom then
            self.restoreGlowingHourGlassDataOnNextRoom = false
            restoreGlowingHourGlassBackup(
                nil,
                self.saveDataMap,
                self.saveDataConditionalFuncMap,
                self.saveDataGlowingHourGlassMap,
                self.classConstructors
            )
        else
            makeGlowingHourGlassBackup(nil, self.saveDataMap, self.saveDataConditionalFuncMap, self.saveDataGlowingHourGlassMap)
        end
    end
    self.callbacksUsed = {{ModCallback.POST_USE_ITEM, self.postUseItemGlowingHourGlass, {CollectibleType.GLOWING_HOUR_GLASS}}, {ModCallback.POST_PLAYER_INIT, self.postPlayerInit}, {ModCallback.PRE_GAME_EXIT, self.preGameExit}, {ModCallback.POST_NEW_LEVEL, self.postNewLevel}}
    self.customCallbacksUsed = {{ModCallbackCustom.POST_NEW_ROOM_EARLY, self.postNewRoomEarly}}
    self.mod = mod
end
function SaveDataManager.prototype.saveDataManager(self, key, v, conditionalFunc)
    if isTSTLClass(nil, key) then
        local className = getTSTLClassName(nil, key)
        assertDefined(nil, className, "Failed to get the class name for the submitted class (as part of the \"key\" parameter) when registering new data with the save data manager.")
        key = className
    end
    if not isString(nil, key) then
        error("The save data manager requires that keys are strings or TSTL classes. You tried to use a key of type: " .. __TS__TypeOf(key))
    end
    if self.saveDataMap[key] ~= nil then
        error("The save data manager is already managing save data for a key of: " .. key)
    end
    self:storeClassConstructorsFromObject(v)
    self.saveDataMap[key] = v
    if conditionalFunc == false then
        conditionalFunc = function() return false end
    end
    local saveDataKeys = __TS__ObjectKeys(v)
    if #saveDataKeys == 1 and saveDataKeys[1] == "room" then
        conditionalFunc = function() return false end
    end
    local saveDataCopy = deepCopy(nil, v, SerializationType.NONE, key)
    self.saveDataDefaultsMap[key] = saveDataCopy
    if conditionalFunc ~= nil then
        self.saveDataConditionalFuncMap[key] = conditionalFunc
    end
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManager", true)
function SaveDataManager.prototype.storeClassConstructorsFromObject(self, luaMap)
    local tstlClassName = getTSTLClassName(nil, luaMap)
    if tstlClassName ~= nil and not NON_USER_DEFINED_CLASS_NAMES:has(tstlClassName) then
        self.classConstructors[tstlClassName] = luaMap
    end
    for _key, value in pairs(luaMap) do
        if isTable(nil, value) then
            self:storeClassConstructorsFromObject(value)
        end
    end
end
function SaveDataManager.prototype.saveDataManagerLoad(self)
    loadFromDisk(nil, self.mod, self.saveDataMap, self.classConstructors)
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerLoad", true)
function SaveDataManager.prototype.saveDataManagerSave(self)
    saveToDisk(nil, self.mod, self.saveDataMap, self.saveDataConditionalFuncMap)
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerSave", true)
function SaveDataManager.prototype.saveDataManagerSetGlobal(self)
    g = self.saveDataMap
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerSetGlobal", true)
function SaveDataManager.prototype.saveDataManagerRegisterClass(self, ...)
    local tstlClasses = {...}
    for ____, tstlClass in ipairs(tstlClasses) do
        local name = tstlClass.name
        assertDefined(nil, name, "Failed to register a class with the save data manager due to not being able to derive the name of the class.")
        self.classConstructors[name] = tstlClass
    end
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerRegisterClass", true)
function SaveDataManager.prototype.saveDataManagerRemove(self, key)
    if not isString(nil, key) then
        error("The save data manager requires that keys are strings. You tried to use a key of type: " .. __TS__TypeOf(key))
    end
    if not (self.saveDataMap[key] ~= nil) then
        error("The save data manager is not managing save data for a key of: " .. key)
    end
    self.saveDataMap[key] = nil
    self.saveDataDefaultsMap[key] = nil
    self.saveDataConditionalFuncMap[key] = nil
    self.saveDataGlowingHourGlassMap[key] = nil
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerRemove", true)
function SaveDataManager.prototype.saveDataManagerReset(self, key, childObjectKey)
    if not isString(nil, key) then
        error("The save data manager requires that keys are strings. You tried to use a key of type: " .. __TS__TypeOf(key))
    end
    local saveData = self.saveDataMap[key]
    assertDefined(nil, saveData, "The save data manager is not managing save data for a key of: " .. key)
    restoreDefaultForFeatureKey(
        nil,
        self.saveDataDefaultsMap,
        key,
        saveData,
        childObjectKey
    )
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerReset", true)
function SaveDataManager.prototype.saveDataManagerInMenu(self)
    return not self.inARun
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerInMenu", true)
function SaveDataManager.prototype.saveDataManagerLogSubscribers(self)
    log("List of save data manager subscribers:")
    local keys = __TS__ObjectKeys(self.saveDataMap)
    __TS__ArraySort(keys)
    for ____, key in ipairs(keys) do
        log("- " .. key)
    end
end
__TS__DecorateLegacy({Exported}, SaveDataManager.prototype, "saveDataManagerLogSubscribers", true)
return ____exports
