local ____exports = {}
local GOLDEN_TRINKET_ADJUSTMENT
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local TrinketType = ____isaac_2Dtypescript_2Ddefinitions.TrinketType
local ____cachedClasses = require("core.cachedClasses")
local itemConfig = ____cachedClasses.itemConfig
local ____constants = require("core.constants")
local BLIND_ITEM_PNG_PATH = ____constants.BLIND_ITEM_PNG_PATH
local ____constantsFirstLast = require("core.constantsFirstLast")
local LAST_VANILLA_TRINKET_TYPE = ____constantsFirstLast.LAST_VANILLA_TRINKET_TYPE
local ____MysteriousPaperEffect = require("enums.MysteriousPaperEffect")
local MysteriousPaperEffect = ____MysteriousPaperEffect.MysteriousPaperEffect
local ____trinketDescriptions = require("objects.trinketDescriptions")
local DEFAULT_TRINKET_DESCRIPTION = ____trinketDescriptions.DEFAULT_TRINKET_DESCRIPTION
local TRINKET_DESCRIPTIONS = ____trinketDescriptions.TRINKET_DESCRIPTIONS
local ____trinketNames = require("objects.trinketNames")
local DEFAULT_TRINKET_NAME = ____trinketNames.DEFAULT_TRINKET_NAME
local TRINKET_NAMES = ____trinketNames.TRINKET_NAMES
local ____entities = require("functions.entities")
local getEntityID = ____entities.getEntityID
local ____enums = require("functions.enums")
local getEnumLength = ____enums.getEnumLength
local ____flag = require("functions.flag")
local hasFlag = ____flag.hasFlag
local ____pickupVariants = require("functions.pickupVariants")
local isTrinket = ____pickupVariants.isTrinket
local ____sprites = require("functions.sprites")
local clearSprite = ____sprites.clearSprite
local ____types = require("functions.types")
local asNumber = ____types.asNumber
local asTrinketType = ____types.asTrinketType
function ____exports.isGoldenTrinketType(self, trinketType)
    return asNumber(nil, trinketType) > GOLDEN_TRINKET_ADJUSTMENT
end
function ____exports.isVanillaTrinketType(self, trinketType)
    return trinketType <= LAST_VANILLA_TRINKET_TYPE
end
GOLDEN_TRINKET_ADJUSTMENT = 32768
local NUM_MYSTERIOUS_PAPER_EFFECTS = getEnumLength(nil, MysteriousPaperEffect)
local TRINKET_ANM2_PATH = "gfx/005.350_trinket.anm2"
local TRINKET_SPRITE_LAYER = 0
--- Helper function to get the corresponding golden trinket type from a normal trinket type.
-- 
-- If the provided trinket type is already a golden trinket type, then the trinket type will be
-- returned unmodified.
-- 
-- For example, passing `TrinketType.SWALLOWED_PENNY` would result in 32769, which is the value that
-- corresponds to the golden trinket sub-type for Swallowed Penny.
function ____exports.getGoldenTrinketType(self, trinketType)
    return ____exports.isGoldenTrinketType(nil, trinketType) and trinketType or trinketType + GOLDEN_TRINKET_ADJUSTMENT
end
--- Helper function to get the current effect that the Mysterious Paper trinket is providing to the
-- player. Returns undefined if the player does not have the Mysterious Paper trinket.
-- 
-- The Mysterious Paper trinket has four different effects:
-- 
-- - The Polaroid (collectible)
-- - The Negative (collectible)
-- - A Missing Page (trinket)
-- - Missing Poster (trinket)
-- 
-- It rotates between these four effects on every frame. Note that Mysterious Paper will cause the
-- `EntityPlayer.HasCollectible` and `EntityPlayer.HasTrinket` methods to return true for the
-- respective items on the particular frame, with the exception of the Missing Poster. (The player
-- will never "have" the Missing Poster, even on the correct corresponding frame.)
-- 
-- @param player The player to look at.
-- @param frameCount Optional. The frame count that corresponds to time the effect will be active.
-- Default is the current frame.
function ____exports.getMysteriousPaperEffectForFrame(self, player, frameCount)
    if frameCount == nil then
        frameCount = player.FrameCount
    end
    if not player:HasTrinket(TrinketType.MYSTERIOUS_PAPER) then
        return nil
    end
    return frameCount % NUM_MYSTERIOUS_PAPER_EFFECTS
end
--- Helper function to get the corresponding normal trinket type from a golden trinket type.
-- 
-- If the provided trinket type is already a normal trinket type, then the trinket type will be
-- returned unmodified.
function ____exports.getNormalTrinketType(self, trinketType)
    return ____exports.isGoldenTrinketType(nil, trinketType) and trinketType - GOLDEN_TRINKET_ADJUSTMENT or trinketType
end
--- Helper function to get the in-game description for a trinket. Returns "Unknown" if the provided
-- trinket type was not valid.
-- 
-- This function works for both vanilla and modded trinkets.
function ____exports.getTrinketDescription(self, trinketType)
    local trinketDescription = TRINKET_DESCRIPTIONS[trinketType]
    if trinketDescription ~= nil then
        return trinketDescription
    end
    local itemConfigItem = itemConfig:GetTrinket(trinketType)
    if itemConfigItem ~= nil then
        return itemConfigItem.Description
    end
    return DEFAULT_TRINKET_DESCRIPTION
end
--- Helper function to get the path to a trinket PNG file. Returns the path to the question mark
-- sprite (i.e. from Curse of the Blind) if the provided trinket type was not valid.
-- 
-- Note that this does not return the file name, but the full path to the trinket's PNG file. The
-- function is named "GfxFilename" to correspond to the associated `ItemConfigItem.GfxFileName`
-- field.
function ____exports.getTrinketGfxFilename(self, trinketType)
    local itemConfigItem = itemConfig:GetTrinket(trinketType)
    if itemConfigItem == nil then
        return BLIND_ITEM_PNG_PATH
    end
    return itemConfigItem.GfxFileName
end
--- Helper function to get the name of a trinket. Returns "Unknown" if the provided trinket type is
-- not valid.
-- 
-- This function works for both vanilla and modded trinkets.
-- 
-- For example, `getTrinketName(TrinketType.SWALLOWED_PENNY)` would return "Swallowed Penny".
function ____exports.getTrinketName(self, trinketType)
    local trinketName = TRINKET_NAMES[trinketType]
    if trinketName ~= nil then
        return trinketName
    end
    local itemConfigItem = itemConfig:GetTrinket(trinketType)
    if itemConfigItem ~= nil then
        return itemConfigItem.Name
    end
    return DEFAULT_TRINKET_NAME
end
function ____exports.isModdedTrinketType(self, trinketType)
    return not ____exports.isVanillaTrinketType(nil, trinketType)
end
function ____exports.isValidTrinketType(self, trinketType)
    local potentialTrinketType = asTrinketType(nil, trinketType)
    local itemConfigItem = itemConfig:GetTrinket(potentialTrinketType)
    return itemConfigItem ~= nil
end
--- Helper function to generate a new sprite based on a collectible. If the provided collectible type
-- is invalid, a sprite with a Curse of the Blind question mark will be returned.
function ____exports.newTrinketSprite(self, trinketType)
    local sprite = Sprite()
    sprite:Load(TRINKET_ANM2_PATH, false)
    local gfxFileName = ____exports.getTrinketGfxFilename(nil, trinketType)
    sprite:ReplaceSpritesheet(TRINKET_SPRITE_LAYER, gfxFileName)
    sprite:LoadGraphics()
    local defaultAnimation = sprite:GetDefaultAnimation()
    sprite:Play(defaultAnimation, true)
    return sprite
end
--- Helper function to change the sprite of a trinket entity.
-- 
-- For more information about removing the trinket sprite, see the documentation for the
-- "clearSprite" helper function.
-- 
-- @param trinket The trinket whose sprite you want to modify.
-- @param pngPath Equal to either the spritesheet path to load (e.g.
-- "gfx/items/trinkets/trinket_001_swallowedpenny.png") or undefined. If undefined,
-- the sprite will be removed, making the trinket effectively invisible (except for
-- the shadow underneath it).
function ____exports.setTrinketSprite(self, trinket, pngPath)
    if not isTrinket(nil, trinket) then
        local entityID = getEntityID(nil, trinket)
        error("The \"setTrinketSprite\" function was given a non-trinket: " .. entityID)
    end
    local sprite = trinket:GetSprite()
    if pngPath == nil then
        clearSprite(nil, sprite)
    else
        sprite:ReplaceSpritesheet(TRINKET_SPRITE_LAYER, pngPath)
        sprite:LoadGraphics()
    end
end
--- Helper function to check in the item config if a given trinket has a given cache flag.
function ____exports.trinketHasCacheFlag(self, trinketType, cacheFlag)
    local itemConfigItem = itemConfig:GetTrinket(trinketType)
    if itemConfigItem == nil then
        return false
    end
    return hasFlag(nil, itemConfigItem.CacheFlags, cacheFlag)
end
return ____exports
