local ____lualib = require("lualib_bundle")
local __TS__ArraySome = ____lualib.__TS__ArraySome
local __TS__ArrayFind = ____lualib.__TS__ArrayFind
local ____exports = {}
local willVanillaVersusScreenPlay, getPlayerPNGPaths, getBossPNGPaths, getBossPNGPathsCustom
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local BossID = ____isaac_2Dtypescript_2Ddefinitions.BossID
local PlayerType = ____isaac_2Dtypescript_2Ddefinitions.PlayerType
local RoomType = ____isaac_2Dtypescript_2Ddefinitions.RoomType
local SoundEffect = ____isaac_2Dtypescript_2Ddefinitions.SoundEffect
local StageID = ____isaac_2Dtypescript_2Ddefinitions.StageID
local ____cachedClasses = require("core.cachedClasses")
local game = ____cachedClasses.game
local sfxManager = ____cachedClasses.sfxManager
local ____array = require("functions.array")
local arrayRemove = ____array.arrayRemove
local ____bosses = require("functions.bosses")
local getBosses = ____bosses.getBosses
local ____roomData = require("functions.roomData")
local getRoomSubType = ____roomData.getRoomSubType
local ____string = require("functions.string")
local removeCharactersBefore = ____string.removeCharactersBefore
local ____ui = require("functions.ui")
local getScreenCenterPos = ____ui.getScreenCenterPos
local ____utils = require("functions.utils")
local eRange = ____utils.eRange
local ____versusScreen = require("functions.versusScreen")
local getBossNamePNGFilePath = ____versusScreen.getBossNamePNGFilePath
local getBossPortraitPNGFilePath = ____versusScreen.getBossPortraitPNGFilePath
local getCharacterNamePNGFilePath = ____versusScreen.getCharacterNamePNGFilePath
local getCharacterPortraitPNGFilePath = ____versusScreen.getCharacterPortraitPNGFilePath
local ____versusScreenBackgroundColors = require("objects.versusScreenBackgroundColors")
local VERSUS_SCREEN_BACKGROUND_COLORS = ____versusScreenBackgroundColors.VERSUS_SCREEN_BACKGROUND_COLORS
local ____versusScreenDirtSpotColors = require("objects.versusScreenDirtSpotColors")
local VERSUS_SCREEN_DIRT_SPOT_COLORS = ____versusScreenDirtSpotColors.VERSUS_SCREEN_DIRT_SPOT_COLORS
local ____constants = require("classes.features.other.customStages.constants")
local CUSTOM_FLOOR_STAGE = ____constants.CUSTOM_FLOOR_STAGE
local CUSTOM_FLOOR_STAGE_TYPE = ____constants.CUSTOM_FLOOR_STAGE_TYPE
local CUSTOM_STAGE_FEATURE_NAME = ____constants.CUSTOM_STAGE_FEATURE_NAME
local DEFAULT_BASE_STAGE = ____constants.DEFAULT_BASE_STAGE
local DEFAULT_BASE_STAGE_TYPE = ____constants.DEFAULT_BASE_STAGE_TYPE
local ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH = ____constants.ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH
local ____v = require("classes.features.other.customStages.v")
local v = ____v.v
function willVanillaVersusScreenPlay(self)
    local bosses = getBosses(nil)
    return __TS__ArraySome(
        bosses,
        function(____, boss) return boss:GetBossID() ~= 0 end
    )
end
function getPlayerPNGPaths(self)
    local player = Isaac.GetPlayer()
    local character = player:GetPlayerType()
    if character == PlayerType.POSSESSOR then
        error("Failed to get the player PNG paths since they are a possessor.")
    end
    local namePNGPath = getCharacterNamePNGFilePath(nil, character)
    local portraitPNGPath = getCharacterPortraitPNGFilePath(nil, character)
    return {namePNGPath = namePNGPath, portraitPNGPath = portraitPNGPath}
end
function getBossPNGPaths(self, customStage)
    local paths = getBossPNGPathsCustom(nil, customStage)
    if paths ~= nil then
        return paths
    end
    local bosses = getBosses(nil)
    local firstBoss = bosses[1]
    local bossID = firstBoss == nil and 0 or firstBoss:GetBossID()
    if bossID == 0 then
        local questionMarkPath = getBossNamePNGFilePath(nil, BossID.BLUE_BABY)
        local namePNGPath = questionMarkPath
        local portraitPNGPath = questionMarkPath
        return {namePNGPath = namePNGPath, portraitPNGPath = portraitPNGPath}
    end
    local namePNGPath = getBossNamePNGFilePath(nil, bossID)
    local portraitPNGPath = getBossPortraitPNGFilePath(nil, bossID)
    return {namePNGPath = namePNGPath, portraitPNGPath = portraitPNGPath}
end
function getBossPNGPathsCustom(self, customStage)
    if customStage.bossPool == nil then
        return nil
    end
    local roomSubType = getRoomSubType(nil)
    local matchingBossEntry = __TS__ArrayFind(
        customStage.bossPool,
        function(____, bossEntry) return bossEntry.subType == roomSubType end
    )
    if matchingBossEntry == nil then
        return nil
    end
    return matchingBossEntry.versusScreen
end
local DEFAULT_STAGE_ID = StageID.BASEMENT
local VERSUS_SCREEN_ANIMATION_NAME = "Scene"
--- The layers range from 0 to 13.
local NUM_VERSUS_SCREEN_ANM2_LAYERS = 14
--- Corresponds to "resources/gfx/ui/boss/versusscreen.anm2".
local VersusScreenLayer = {}
VersusScreenLayer.BACKGROUND = 0
VersusScreenLayer[VersusScreenLayer.BACKGROUND] = "BACKGROUND"
VersusScreenLayer.FRAME = 1
VersusScreenLayer[VersusScreenLayer.FRAME] = "FRAME"
VersusScreenLayer.BOSS_SPOT = 2
VersusScreenLayer[VersusScreenLayer.BOSS_SPOT] = "BOSS_SPOT"
VersusScreenLayer.PLAYER_SPOT = 3
VersusScreenLayer[VersusScreenLayer.PLAYER_SPOT] = "PLAYER_SPOT"
VersusScreenLayer.BOSS_PORTRAIT = 4
VersusScreenLayer[VersusScreenLayer.BOSS_PORTRAIT] = "BOSS_PORTRAIT"
VersusScreenLayer.PLAYER_PORTRAIT = 5
VersusScreenLayer[VersusScreenLayer.PLAYER_PORTRAIT] = "PLAYER_PORTRAIT"
VersusScreenLayer.PLAYER_NAME = 6
VersusScreenLayer[VersusScreenLayer.PLAYER_NAME] = "PLAYER_NAME"
VersusScreenLayer.BOSS_NAME = 7
VersusScreenLayer[VersusScreenLayer.BOSS_NAME] = "BOSS_NAME"
VersusScreenLayer.VS_TEXT = 8
VersusScreenLayer[VersusScreenLayer.VS_TEXT] = "VS_TEXT"
VersusScreenLayer.BOSS_DOUBLE = 9
VersusScreenLayer[VersusScreenLayer.BOSS_DOUBLE] = "BOSS_DOUBLE"
VersusScreenLayer.DT_TEXT = 10
VersusScreenLayer[VersusScreenLayer.DT_TEXT] = "DT_TEXT"
VersusScreenLayer.OVERLAY = 11
VersusScreenLayer[VersusScreenLayer.OVERLAY] = "OVERLAY"
VersusScreenLayer.PLAYER_PORTRAIT_ALT = 12
VersusScreenLayer[VersusScreenLayer.PLAYER_PORTRAIT_ALT] = "PLAYER_PORTRAIT_ALT"
VersusScreenLayer.BOSS_PORTRAIT_GROUND = 13
VersusScreenLayer[VersusScreenLayer.BOSS_PORTRAIT_GROUND] = "BOSS_PORTRAIT_GROUND"
VersusScreenLayer.BOSS_PORTRAIT_2_GROUND = 14
VersusScreenLayer[VersusScreenLayer.BOSS_PORTRAIT_2_GROUND] = "BOSS_PORTRAIT_2_GROUND"
--- These are the non-special layers that we will render last.
local OTHER_ANM2_LAYERS = arrayRemove(
    nil,
    eRange(nil, NUM_VERSUS_SCREEN_ANM2_LAYERS),
    VersusScreenLayer.BACKGROUND,
    VersusScreenLayer.BOSS_SPOT,
    VersusScreenLayer.PLAYER_SPOT,
    VersusScreenLayer.OVERLAY,
    VersusScreenLayer.PLAYER_PORTRAIT_ALT
)
local VANILLA_VERSUS_PLAYBACK_SPEED = 0.5
--- We lazy load the sprite when first needed.
local versusScreenSprite = Sprite()
--- We lazy load the sprite when first needed.
-- 
-- Unfortunately, we must split the background layer into an entirely different sprite so that we
-- can color it with the `Color` field.
local versusScreenBackgroundSprite = Sprite()
--- We lazy load the sprite when first needed.
-- 
-- Unfortunately, we must split the dirt layer into an entirely different sprite so that we can
-- color it with the `Color` field.
local versusScreenDirtSpotSprite = Sprite()
function ____exports.playVersusScreenAnimation(self, customStage, disableAllSound, pause, runInNFrames)
    local room = game:GetRoom()
    local roomType = room:GetType()
    local roomCleared = room:IsClear()
    local hud = game:GetHUD()
    if roomType ~= RoomType.BOSS then
        return
    end
    if roomCleared then
        return
    end
    if willVanillaVersusScreenPlay(nil) then
        local level = game:GetLevel()
        level:SetStage(DEFAULT_BASE_STAGE, DEFAULT_BASE_STAGE_TYPE)
        runInNFrames:runNextGameFrame(function()
            local futureLevel = game:GetLevel()
            futureLevel:SetStage(CUSTOM_FLOOR_STAGE, CUSTOM_FLOOR_STAGE_TYPE)
        end)
        return
    end
    v.run.showingBossVersusScreen = true
    pause:pause()
    hud:SetVisible(false)
    disableAllSound:disableAllSound(CUSTOM_STAGE_FEATURE_NAME)
    if not versusScreenSprite:IsLoaded() then
        versusScreenSprite:Load("gfx/ui/boss/versusscreen.anm2", false)
        versusScreenSprite:ReplaceSpritesheet(VersusScreenLayer.OVERLAY, ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH .. "/overlay.png")
    end
    do
        local ____getPlayerPNGPaths_result_0 = getPlayerPNGPaths(nil)
        local namePNGPath = ____getPlayerPNGPaths_result_0.namePNGPath
        local portraitPNGPath = ____getPlayerPNGPaths_result_0.portraitPNGPath
        versusScreenSprite:ReplaceSpritesheet(VersusScreenLayer.PLAYER_NAME, namePNGPath)
        versusScreenSprite:ReplaceSpritesheet(VersusScreenLayer.PLAYER_PORTRAIT, portraitPNGPath)
    end
    do
        local ____getBossPNGPaths_result_1 = getBossPNGPaths(nil, customStage)
        local namePNGPath = ____getBossPNGPaths_result_1.namePNGPath
        local portraitPNGPath = ____getBossPNGPaths_result_1.portraitPNGPath
        local trimmedNamePNGPath = removeCharactersBefore(nil, namePNGPath, "gfx/")
        versusScreenSprite:ReplaceSpritesheet(VersusScreenLayer.BOSS_NAME, trimmedNamePNGPath)
        local trimmedPortraitPNGPath = removeCharactersBefore(nil, portraitPNGPath, "gfx/")
        versusScreenSprite:ReplaceSpritesheet(VersusScreenLayer.BOSS_PORTRAIT, trimmedPortraitPNGPath)
    end
    versusScreenSprite:LoadGraphics()
    if not versusScreenBackgroundSprite:IsLoaded() then
        versusScreenBackgroundSprite:Load("gfx/ui/boss/versusscreen.anm2", true)
    end
    local backgroundColor = VERSUS_SCREEN_BACKGROUND_COLORS[DEFAULT_STAGE_ID]
    local ____opt_2 = customStage.versusScreen
    if (____opt_2 and ____opt_2.backgroundColor) ~= nil then
        local ____customStage_versusScreen_backgroundColor_4 = customStage.versusScreen.backgroundColor
        local r = ____customStage_versusScreen_backgroundColor_4.r
        local g = ____customStage_versusScreen_backgroundColor_4.g
        local b = ____customStage_versusScreen_backgroundColor_4.b
        local a = ____customStage_versusScreen_backgroundColor_4.a
        backgroundColor = Color(r, g, b, a)
    end
    versusScreenBackgroundSprite.Color = backgroundColor
    if not versusScreenDirtSpotSprite:IsLoaded() then
        versusScreenDirtSpotSprite:Load("gfx/ui/boss/versusscreen.anm2", true)
    end
    local dirtSpotColor = VERSUS_SCREEN_DIRT_SPOT_COLORS[DEFAULT_STAGE_ID]
    local ____opt_5 = customStage.versusScreen
    if (____opt_5 and ____opt_5.dirtSpotColor) ~= nil then
        local ____customStage_versusScreen_dirtSpotColor_7 = customStage.versusScreen.dirtSpotColor
        local r = ____customStage_versusScreen_dirtSpotColor_7.r
        local g = ____customStage_versusScreen_dirtSpotColor_7.g
        local b = ____customStage_versusScreen_dirtSpotColor_7.b
        dirtSpotColor = Color(r, g, b)
    end
    versusScreenDirtSpotSprite.Color = dirtSpotColor
    for ____, sprite in ipairs({versusScreenBackgroundSprite, versusScreenDirtSpotSprite, versusScreenSprite}) do
        sprite:Play(VERSUS_SCREEN_ANIMATION_NAME, true)
        sprite.PlaybackSpeed = VANILLA_VERSUS_PLAYBACK_SPEED
    end
end
local function finishVersusScreenAnimation(self, pause, disableAllSound)
    local hud = game:GetHUD()
    v.run.showingBossVersusScreen = false
    pause:unpause()
    hud:SetVisible(true)
    disableAllSound:enableAllSound(CUSTOM_STAGE_FEATURE_NAME)
    sfxManager:Play(SoundEffect.CASTLE_PORTCULLIS)
end
function ____exports.versusScreenPostRender(self, pause, disableAllSound)
    if not v.run.showingBossVersusScreen then
        return
    end
    if versusScreenSprite:IsFinished(VERSUS_SCREEN_ANIMATION_NAME) then
        finishVersusScreenAnimation(nil, pause, disableAllSound)
        return
    end
    local position = getScreenCenterPos(nil)
    versusScreenBackgroundSprite:RenderLayer(VersusScreenLayer.BACKGROUND, position)
    versusScreenBackgroundSprite:Update()
    versusScreenSprite:RenderLayer(VersusScreenLayer.OVERLAY, position)
    versusScreenDirtSpotSprite:RenderLayer(VersusScreenLayer.BOSS_SPOT, position)
    versusScreenDirtSpotSprite:RenderLayer(VersusScreenLayer.PLAYER_SPOT, position)
    versusScreenDirtSpotSprite:Update()
    for ____, layerID in ipairs(OTHER_ANM2_LAYERS) do
        versusScreenSprite:RenderLayer(layerID, position)
    end
    versusScreenSprite:Update()
end
return ____exports
