local ____lualib = require("lualib_bundle")
local __TS__ArraySome = ____lualib.__TS__ArraySome
local __TS__ArrayEvery = ____lualib.__TS__ArrayEvery
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__ArrayMap = ____lualib.__TS__ArrayMap
local ____exports = {}
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local PlayerType = ____isaac_2Dtypescript_2Ddefinitions.PlayerType
local TrinketSlot = ____isaac_2Dtypescript_2Ddefinitions.TrinketSlot
local TrinketType = ____isaac_2Dtypescript_2Ddefinitions.TrinketType
local ____cachedEnumValues = require("cachedEnumValues")
local TRINKET_SLOT_VALUES = ____cachedEnumValues.TRINKET_SLOT_VALUES
local ____cachedClasses = require("core.cachedClasses")
local itemConfig = ____cachedClasses.itemConfig
local ____playerIndex = require("functions.playerIndex")
local getAllPlayers = ____playerIndex.getAllPlayers
local getPlayers = ____playerIndex.getPlayers
local ____players = require("functions.players")
local isCharacter = ____players.isCharacter
function ____exports.addTrinketCostume(self, player, trinketType)
    local itemConfigTrinket = itemConfig:GetTrinket(trinketType)
    if itemConfigTrinket == nil then
        return
    end
    player:AddCostume(itemConfigTrinket, false)
end
--- Helper function to check to see if any player has a particular trinket.
-- 
-- @param trinketType The trinket type to check for.
-- @param ignoreModifiers If set to true, only counts trinkets the player actually holds and ignores
-- effects granted by other items. Default is false.
function ____exports.anyPlayerHasTrinket(self, trinketType, ignoreModifiers)
    local players = getAllPlayers(nil)
    return __TS__ArraySome(
        players,
        function(____, player) return player:HasTrinket(trinketType, ignoreModifiers) end
    )
end
--- Returns the slot number corresponding to where a trinket can be safely inserted.
-- 
-- For example:
-- 
-- ```ts
-- const player = Isaac.GetPlayer();
-- const trinketSlot = getOpenTrinketSlotNum(player);
-- if (trinketSlot !== undefined) {
--   // They have one or more open trinket slots
--   player.AddTrinket(TrinketType.SWALLOWED_PENNY);
-- }
-- ```
function ____exports.getOpenTrinketSlot(self, player)
    local maxTrinkets = player:GetMaxTrinkets()
    local trinketType1 = player:GetTrinket(TrinketSlot.SLOT_1)
    local trinketType2 = player:GetTrinket(TrinketSlot.SLOT_2)
    if maxTrinkets == 1 then
        return trinketType1 == TrinketType.NULL and 0 or nil
    end
    if maxTrinkets == 2 then
        if trinketType1 == TrinketType.NULL then
            return 0
        end
        return trinketType2 == TrinketType.NULL and 1 or nil
    end
    error("The player has an unknown number of trinket slots: " .. tostring(maxTrinkets))
end
--- Helper function to get all of the trinkets that the player is currently holding. This will not
-- include any smelted trinkets.
function ____exports.getPlayerTrinkets(self, player)
    local trinketTypes = {}
    for ____, trinketSlot in ipairs(TRINKET_SLOT_VALUES) do
        local trinketType = player:GetTrinket(trinketSlot)
        if trinketType ~= TrinketType.NULL then
            trinketTypes[#trinketTypes + 1] = trinketType
        end
    end
    return trinketTypes
end
--- Helper function to get only the players that have a certain trinket.
-- 
-- This function is variadic, meaning that you can supply as many trinket types as you want to check
-- for. It only returns the players that have all of the trinkets.
function ____exports.getPlayersWithTrinket(self, ...)
    local trinketTypes = {...}
    local players = getPlayers(nil)
    return __TS__ArrayFilter(
        players,
        function(____, player) return __TS__ArrayEvery(
            trinketTypes,
            function(____, trinketType) return player:HasTrinket(trinketType) end
        ) end
    )
end
--- Helper function to check to see if the player is holding one or more trinkets.
function ____exports.hasAnyTrinket(self, player)
    local playerTrinketTypes = __TS__ArrayMap(
        TRINKET_SLOT_VALUES,
        function(____, trinketSlot) return player:GetTrinket(trinketSlot) end
    )
    return __TS__ArraySome(
        playerTrinketTypes,
        function(____, trinketType) return trinketType ~= TrinketType.NULL end
    )
end
--- Returns whether the player can hold an additional trinket, beyond what they are currently
-- carrying. This takes into account items that modify the max number of trinkets, like Mom's Purse.
-- 
-- If the player is the Tainted Soul, this always returns false, since that character cannot pick up
-- items. (Only Tainted Forgotten can pick up items.)
function ____exports.hasOpenTrinketSlot(self, player)
    if isCharacter(nil, player, PlayerType.SOUL_B) then
        return false
    end
    local openTrinketSlot = ____exports.getOpenTrinketSlot(nil, player)
    return openTrinketSlot ~= nil
end
--- Helper function to check to see if a player has one or more trinkets.
-- 
-- This function is variadic, meaning that you can supply as many trinket types as you want to check
-- for. Returns true if the player has any of the supplied trinket types.
-- 
-- This function always passes `false` to the `ignoreModifiers` argument.
function ____exports.hasTrinket(self, player, ...)
    local trinketTypes = {...}
    return __TS__ArraySome(
        trinketTypes,
        function(____, trinketType) return player:HasTrinket(trinketType) end
    )
end
--- Helper function to remove all of the held trinkets from a player.
-- 
-- This will not remove any smelted trinkets, unless the player happens to also be holding a trinket
-- that they have smelted. (In that case, both the held and the smelted trinket will be removed.)
function ____exports.removeAllPlayerTrinkets(self, player)
    for ____, trinketSlot in ipairs(TRINKET_SLOT_VALUES) do
        do
            local trinketType = player:GetTrinket(trinketSlot)
            if trinketType == TrinketType.NULL then
                goto __continue25
            end
            local alreadyHasTrinket
            repeat
                do
                    player:TryRemoveTrinket(trinketType)
                    alreadyHasTrinket = player:HasTrinket(trinketType)
                end
            until not alreadyHasTrinket
        end
        ::__continue25::
    end
end
--- Helper function to remove a trinket costume from a player. Use this helper function to avoid
-- having to request the trinket from the item config.
function ____exports.removeTrinketCostume(self, player, trinketType)
    local itemConfigTrinket = itemConfig:GetTrinket(trinketType)
    if itemConfigTrinket == nil then
        return
    end
    player:RemoveCostume(itemConfigTrinket)
end
return ____exports
