local ____lualib = require("lualib_bundle")
local __TS__Spread = ____lualib.__TS__Spread
local ____exports = {}
local checkEndTopStreakText, trackMapInputPressed, checkStartBottomStreakText, checkEndBottomStreakText, renderStreakText, UI_STREAK_ANIMATION_END_FRAMES, TEXT_STAY_FRAME, TEXT_OUT_FRAME, STREAK_TEXT_BOTTOM_Y_OFFSET, NUM_RENDER_FRAMES_MAP_HELD_BEFORE_STREAK_TEXT, TEXT_IN_ADJUSTMENTS, TEXT_OUT_ADJUSTMENTS, TEXT_IN_SCALES, TEXT_OUT_SCALES
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local ButtonAction = ____isaac_2Dtypescript_2Ddefinitions.ButtonAction
local ____cachedEnumValues = require("arrays.cachedEnumValues")
local CONTROLLER_INDEX_VALUES = ____cachedEnumValues.CONTROLLER_INDEX_VALUES
local ____cachedClasses = require("core.cachedClasses")
local fonts = ____cachedClasses.fonts
local game = ____cachedClasses.game
local ____constants = require("core.constants")
local KColorDefault = ____constants.KColorDefault
local VectorOne = ____constants.VectorOne
local ____UIStreakAnimation = require("enums.private.UIStreakAnimation")
local UIStreakAnimation = ____UIStreakAnimation.UIStreakAnimation
local ____frames = require("functions.frames")
local getElapsedGameFramesSince = ____frames.getElapsedGameFramesSince
local getElapsedRenderFramesSince = ____frames.getElapsedRenderFramesSince
local ____ui = require("functions.ui")
local getScreenBottomCenterPos = ____ui.getScreenBottomCenterPos
local getScreenTopCenterPos = ____ui.getScreenTopCenterPos
local ____v = require("classes.features.other.customStages.v")
local v = ____v.v
function checkEndTopStreakText(self)
    if v.run.topStreakTextStartedRenderFrame == nil or v.run.topStreakText.animation ~= UIStreakAnimation.TEXT_STAY then
        return
    end
    local elapsedFrames = getElapsedRenderFramesSince(nil, v.run.topStreakTextStartedRenderFrame)
    if elapsedFrames >= 115 then
        v.run.topStreakText.animation = UIStreakAnimation.TEXT
        v.run.topStreakText.frame = TEXT_OUT_FRAME - 2
    end
end
function trackMapInputPressed(self)
    local gameFrameCount = game:GetFrameCount()
    for ____, controllerIndex in ipairs(CONTROLLER_INDEX_VALUES) do
        local oldPushedMapFrame = v.run.controllerIndexPushingMapRenderFrame:get(controllerIndex)
        local isPushingMap = Input.IsActionPressed(ButtonAction.MAP, controllerIndex)
        if isPushingMap then
            if oldPushedMapFrame == nil then
                v.run.controllerIndexPushingMapRenderFrame:set(controllerIndex, gameFrameCount)
            end
        else
            v.run.controllerIndexPushingMapRenderFrame:delete(controllerIndex)
        end
    end
end
function checkStartBottomStreakText(self)
    if v.run.bottomStreakText.animation ~= UIStreakAnimation.NONE then
        return
    end
    local pushedMapFrames = {__TS__Spread(v.run.controllerIndexPushingMapRenderFrame:values())}
    if #pushedMapFrames == 0 then
        return
    end
    local earliestFrame = math.min(table.unpack(pushedMapFrames))
    local elapsedFrames = getElapsedGameFramesSince(nil, earliestFrame)
    if elapsedFrames >= NUM_RENDER_FRAMES_MAP_HELD_BEFORE_STREAK_TEXT then
        v.run.bottomStreakText.animation = UIStreakAnimation.TEXT
        v.run.bottomStreakText.frame = 0
    end
end
function checkEndBottomStreakText(self)
    if v.run.bottomStreakText.animation ~= UIStreakAnimation.TEXT_STAY then
        return
    end
    local pushedMapFrames = {__TS__Spread(v.run.controllerIndexPushingMapRenderFrame:values())}
    if #pushedMapFrames == 0 then
        v.run.bottomStreakText.animation = UIStreakAnimation.TEXT
        v.run.bottomStreakText.frame = TEXT_OUT_FRAME - 2
    end
end
function renderStreakText(self, customStage, streakText, position)
    if streakText.animation == UIStreakAnimation.NONE then
        return
    end
    if streakText.animation ~= UIStreakAnimation.TEXT_STAY then
        local ____streakText_0 = streakText
        local pauseFrame = ____streakText_0.pauseFrame
        streakText.pauseFrame = not streakText.pauseFrame
        if not pauseFrame then
            streakText.frame = streakText.frame + 1
        end
    end
    local endFrame = UI_STREAK_ANIMATION_END_FRAMES[streakText.animation]
    if streakText.frame > endFrame then
        streakText.animation = UIStreakAnimation.NONE
        streakText.frame = 0
        return
    end
    if streakText.animation == UIStreakAnimation.TEXT and streakText.frame == TEXT_STAY_FRAME then
        streakText.animation = UIStreakAnimation.TEXT_STAY
        streakText.frame = 0
    end
    local isPaused = game:IsPaused()
    if isPaused then
        return
    end
    local font = fonts.upheaval
    local ____customStage_1 = customStage
    local name = ____customStage_1.name
    local numberSuffix = v.run.firstFloor and "I" or "II"
    local nameWithNumberSuffix = (name .. " ") .. numberSuffix
    local length = font:GetStringWidthUTF8(nameWithNumberSuffix)
    local centeredX = position.X - length / 2
    local adjustment = 0
    local scale = VectorOne
    if streakText.animation == UIStreakAnimation.TEXT then
        if streakText.frame < TEXT_STAY_FRAME then
            adjustment = TEXT_IN_ADJUSTMENTS[streakText.frame + 1] or 0
            scale = TEXT_IN_SCALES[streakText.frame + 1] or VectorOne
        else
            local adjustedFrame = streakText.frame - TEXT_OUT_FRAME
            adjustment = TEXT_OUT_ADJUSTMENTS[adjustedFrame + 1] or 0
            scale = TEXT_OUT_SCALES[adjustedFrame + 1] or VectorOne
        end
    end
    local adjustedX = centeredX + adjustment
    local adjustedY = position.Y + STREAK_TEXT_BOTTOM_Y_OFFSET
    font:DrawStringScaled(
        nameWithNumberSuffix,
        adjustedX,
        adjustedY,
        scale.X,
        scale.Y,
        KColorDefault
    )
end
UI_STREAK_ANIMATION_END_FRAMES = {[UIStreakAnimation.NONE] = 0, [UIStreakAnimation.TEXT] = 69, [UIStreakAnimation.TEXT_STAY] = 1}
--- This must match the name of the shader in "shaders.xml".
local EMPTY_SHADER_NAME = "IsaacScript-RenderAboveHUD"
TEXT_STAY_FRAME = 8
TEXT_OUT_FRAME = 60
--- This matches the offset that the vanilla game uses; determined via trial and error.
local STREAK_SPRITE_TOP_OFFSET = Vector(0, 47)
--- This matches the offset that the vanilla game uses; determined via trial and error.
local STREAK_SPRITE_BOTTOM_OFFSET = Vector(0, -48.25)
STREAK_TEXT_BOTTOM_Y_OFFSET = -9
NUM_RENDER_FRAMES_MAP_HELD_BEFORE_STREAK_TEXT = 11
TEXT_IN_ADJUSTMENTS = {
    -800,
    -639,
    -450,
    -250,
    -70,
    10,
    6,
    3
}
TEXT_OUT_ADJUSTMENTS = {
    0,
    -5,
    -10,
    -15,
    -20,
    144,
    308,
    472,
    636,
    800
}
TEXT_IN_SCALES = {
    Vector(3, 0.2),
    Vector(2.6, 0.36),
    Vector(2.2, 0.52),
    Vector(1.8, 0.68),
    Vector(1.4, 0.84),
    Vector(0.95, 1.05),
    Vector(0.97, 1.03),
    Vector(0.98, 1.02)
}
TEXT_OUT_SCALES = {
    Vector(1, 1),
    Vector(0.99, 1.03),
    Vector(0.98, 1.05),
    Vector(0.96, 1.08),
    Vector(0.95, 1.1),
    Vector(1.36, 0.92),
    Vector(1.77, 0.74),
    Vector(2.18, 0.56),
    Vector(2.59, 0.38),
    Vector(3, 0.2)
}
function ____exports.streakTextPostRender(self)
    checkEndTopStreakText(nil)
    trackMapInputPressed(nil)
    checkStartBottomStreakText(nil)
    checkEndBottomStreakText(nil)
end
function ____exports.streakTextGetShaderParams(self, customStage, shaderName)
    if shaderName ~= EMPTY_SHADER_NAME then
        return
    end
    local topCenterPos = getScreenTopCenterPos(nil)
    local topStreakPosition = topCenterPos + STREAK_SPRITE_TOP_OFFSET
    renderStreakText(nil, customStage, v.run.topStreakText, topStreakPosition)
    local bottomCenterPos = getScreenBottomCenterPos(nil)
    local bottomStreakPosition = bottomCenterPos + STREAK_SPRITE_BOTTOM_OFFSET
    renderStreakText(nil, customStage, v.run.bottomStreakText, bottomStreakPosition)
end
function ____exports.topStreakTextStart(self)
    local level = game:GetLevel()
    local renderFrameCount = Isaac.GetFrameCount()
    level:ShowName(false)
    v.run.topStreakText.animation = UIStreakAnimation.TEXT
    v.run.topStreakText.frame = 0
    v.run.topStreakTextStartedRenderFrame = renderFrameCount
end
return ____exports
