local ____lualib = require("lualib_bundle")
local __TS__Class = ____lualib.__TS__Class
local __TS__ClassExtends = ____lualib.__TS__ClassExtends
local __TS__DecorateLegacy = ____lualib.__TS__DecorateLegacy
local ____exports = {}
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local CollectibleType = ____isaac_2Dtypescript_2Ddefinitions.CollectibleType
local ModCallback = ____isaac_2Dtypescript_2Ddefinitions.ModCallback
local ____cachedClasses = require("core.cachedClasses")
local game = ____cachedClasses.game
local ____decorators = require("decorators")
local Exported = ____decorators.Exported
local ____frames = require("functions.frames")
local onGameFrame = ____frames.onGameFrame
local onRenderFrame = ____frames.onRenderFrame
local ____Feature = require("classes.private.Feature")
local Feature = ____Feature.Feature
--- By default, callbacks fire in the following order:
-- - `POST_NEW_ROOM` --> `POST_NEW_LEVEL` --> `POST_GAME_STARTED`
-- 
-- It is easier to write mod code if the callbacks run in a more logical order:
-- - `POST_GAME_STARTED` --> `POST_NEW_LEVEL` --> `POST_NEW_ROOM`
-- 
-- `isaacscript-common` provides three new callbacks that change the order to this:
-- - `POST_GAME_STARTED_REORDERED`
-- - `POST_NEW_LEVEL_REORDERED`
-- - `POST_NEW_ROOM_REORDERED`
-- 
-- Additionally, there are some helper functions listed below that can deal with some edge cases
-- that you may run into with these callbacks.
____exports.GameReorderedCallbacks = __TS__Class()
local GameReorderedCallbacks = ____exports.GameReorderedCallbacks
GameReorderedCallbacks.name = "GameReorderedCallbacks"
__TS__ClassExtends(GameReorderedCallbacks, Feature)
function GameReorderedCallbacks.prototype.____constructor(self, postGameStartedReordered, postNewLevelReordered, postNewRoomReordered, postGameStartedReorderedLast)
    Feature.prototype.____constructor(self)
    self.renderFrameRunStarted = nil
    self.currentStage = nil
    self.currentStageType = nil
    self.usedGlowingHourGlass = false
    self.forceNewLevel = false
    self.forceNewRoom = false
    self.postUseItemGlowingHourGlass = function()
        self.usedGlowingHourGlass = true
        return nil
    end
    self.postPlayerInit = function(____, _player)
        if self.renderFrameRunStarted == nil then
            self.renderFrameRunStarted = Isaac.GetFrameCount()
        end
    end
    self.postGameStarted = function(____, isContinued)
        local level = game:GetLevel()
        local stage = level:GetStage()
        local stageType = level:GetStageType()
        local room = game:GetRoom()
        local roomType = room:GetType()
        self:recordCurrentStage()
        self.postGameStartedReordered:fire(isContinued)
        self.postGameStartedReorderedLast:fire(isContinued)
        if not isContinued then
            self.postNewLevelReordered:fire(stage, stageType)
        end
        self.postNewRoomReordered:fire(roomType)
    end
    self.preGameExit = function()
        self.renderFrameRunStarted = nil
    end
    self.postNewLevel = function()
        local level = game:GetLevel()
        local stage = level:GetStage()
        local stageType = level:GetStageType()
        local room = game:GetRoom()
        local roomType = room:GetType()
        if onGameFrame(nil, 0) and not self.forceNewLevel then
            return
        end
        self.forceNewLevel = false
        self:recordCurrentStage()
        self.postNewLevelReordered:fire(stage, stageType)
        self.postNewRoomReordered:fire(roomType)
    end
    self.postNewRoom = function()
        local level = game:GetLevel()
        local stage = level:GetStage()
        local stageType = level:GetStageType()
        local room = game:GetRoom()
        local roomType = room:GetType()
        if self.usedGlowingHourGlass then
            self.usedGlowingHourGlass = false
            if self.currentStage ~= stage or self.currentStageType ~= stageType then
                self:recordCurrentStage()
                self.postNewLevelReordered:fire(stage, stageType)
                self.postNewRoomReordered:fire(roomType)
                return
            end
        end
        if (onGameFrame(nil, 0) or onRenderFrame(nil, self.renderFrameRunStarted) or self.currentStage ~= stage or self.currentStageType ~= stageType) and not self.forceNewRoom then
            return
        end
        self.forceNewRoom = false
        self.postNewRoomReordered:fire(roomType)
    end
    self.callbacksUsed = {
        {ModCallback.POST_USE_ITEM, self.postUseItemGlowingHourGlass, {CollectibleType.GLOWING_HOUR_GLASS}},
        {ModCallback.POST_PLAYER_INIT, self.postPlayerInit},
        {ModCallback.POST_GAME_STARTED, self.postGameStarted},
        {ModCallback.PRE_GAME_EXIT, self.preGameExit},
        {ModCallback.POST_NEW_LEVEL, self.postNewLevel},
        {ModCallback.POST_NEW_ROOM, self.postNewRoom}
    }
    self.postGameStartedReordered = postGameStartedReordered
    self.postNewLevelReordered = postNewLevelReordered
    self.postNewRoomReordered = postNewRoomReordered
    self.postGameStartedReorderedLast = postGameStartedReorderedLast
end
function GameReorderedCallbacks.prototype.recordCurrentStage(self)
    local level = game:GetLevel()
    local stage = level:GetStage()
    local stageType = level:GetStageType()
    self.currentStage = stage
    self.currentStageType = stageType
end
function GameReorderedCallbacks.prototype.forceNewLevelCallback(self)
    self.forceNewLevel = true
end
__TS__DecorateLegacy({Exported}, GameReorderedCallbacks.prototype, "forceNewLevelCallback", true)
function GameReorderedCallbacks.prototype.forceNewRoomCallback(self)
    self.forceNewRoom = true
end
__TS__DecorateLegacy({Exported}, GameReorderedCallbacks.prototype, "forceNewRoomCallback", true)
function GameReorderedCallbacks.prototype.reorderedCallbacksSetStage(self, stage, stageType)
    self.currentStage = stage
    self.currentStageType = stageType
end
__TS__DecorateLegacy({Exported}, GameReorderedCallbacks.prototype, "reorderedCallbacksSetStage", true)
return ____exports
