local ____exports = {}
local ____isaac_2Dtypescript_2Ddefinitions = require("isaac-typescript-definitions")
local CollectibleType = ____isaac_2Dtypescript_2Ddefinitions.CollectibleType
local TrinketSlot = ____isaac_2Dtypescript_2Ddefinitions.TrinketSlot
local TrinketType = ____isaac_2Dtypescript_2Ddefinitions.TrinketType
local ____playerCollectibles = require("functions.playerCollectibles")
local useActiveItemTemp = ____playerCollectibles.useActiveItemTemp
local ____trinkets = require("functions.trinkets")
local getGoldenTrinketType = ____trinkets.getGoldenTrinketType
local ____utils = require("functions.utils")
local ____repeat = ____utils["repeat"]
--- Helper function to temporarily removes a player's held trinkets, if any. This will not remove any
-- smelted trinkets. Use this in combination with the `giveTrinketsBack` function to take away and
-- give back trinkets on the same frame.
-- 
-- @returns Undefined if the player does not have any trinkets, or TrinketSituation if they do.
function ____exports.temporarilyRemoveTrinkets(self, player)
    local trinketType1 = player:GetTrinket(TrinketSlot.SLOT_1)
    local trinketType2 = player:GetTrinket(TrinketSlot.SLOT_2)
    if trinketType1 == TrinketType.NULL and trinketType2 == TrinketType.NULL then
        return nil
    end
    if trinketType1 ~= TrinketType.NULL then
        player:TryRemoveTrinket(trinketType1)
    end
    if trinketType2 ~= TrinketType.NULL then
        player:TryRemoveTrinket(trinketType2)
    end
    return {trinketTypeRemoved = TrinketType.NULL, trinketType1 = trinketType1, trinketType2 = trinketType2, numSmeltedTrinkets = 0}
end
--- Helper function to restore the player's trinkets back to the way they were before the
-- `temporarilyRemoveTrinket` function was used. It will re-smelt any smelted trinkets that were
-- removed.
function ____exports.giveTrinketsBack(self, player, trinketSituation)
    if trinketSituation == nil then
        return
    end
    local trinketType1 = player:GetTrinket(TrinketSlot.SLOT_1)
    local trinketType2 = player:GetTrinket(TrinketSlot.SLOT_2)
    if trinketType1 ~= TrinketType.NULL then
        player:TryRemoveTrinket(trinketType1)
    end
    if trinketType2 ~= TrinketType.NULL then
        player:TryRemoveTrinket(trinketType2)
    end
    ____repeat(
        nil,
        trinketSituation.numSmeltedTrinkets,
        function()
            player:AddTrinket(trinketSituation.trinketTypeRemoved, false)
            useActiveItemTemp(nil, player, CollectibleType.SMELTER)
        end
    )
    if trinketSituation.trinketType1 ~= TrinketType.NULL then
        player:AddTrinket(trinketSituation.trinketType1, false)
    end
    if trinketSituation.trinketType2 ~= TrinketType.NULL then
        player:AddTrinket(trinketSituation.trinketType2, false)
    end
end
--- Helper function to smelt a trinket. Before smelting, this function will automatically remove the
-- trinkets that the player is holding, if any, and then give them back after the new trinket is
-- smelted.
-- 
-- @param player The player to smelt the trinkets to.
-- @param trinketType The trinket type to smelt.
-- @param numTrinkets Optional. If specified, will smelt the given number of trinkets. Use this to
-- avoid calling this function multiple times. Default is 1.
function ____exports.smeltTrinket(self, player, trinketType, numTrinkets)
    if numTrinkets == nil then
        numTrinkets = 1
    end
    local trinketSituation = ____exports.temporarilyRemoveTrinkets(nil, player)
    ____repeat(
        nil,
        numTrinkets,
        function()
            player:AddTrinket(trinketType)
            useActiveItemTemp(nil, player, CollectibleType.SMELTER)
        end
    )
    ____exports.giveTrinketsBack(nil, player, trinketSituation)
end
--- Helper function to smelt two or more different trinkets. If you want to smelt one trinket (or
-- multiple copies of one trinket), then use the `smeltTrinket` helper function instead.
-- 
-- This function is variadic, meaning that you can pass as many trinket types as you want to smelt.
-- 
-- Before smelting, this function will automatically remove the trinkets that the player is holding,
-- if any, and then give them back after the new trinket is smelted.
-- 
-- @param player The player to smelt the trinkets to.
-- @param trinketTypes The trinket types to smelt.
function ____exports.smeltTrinkets(self, player, ...)
    local trinketTypes = {...}
    for ____, trinketType in ipairs(trinketTypes) do
        ____exports.smeltTrinket(nil, player, trinketType)
    end
end
--- Helper function to temporarily remove a specific kind of trinket from the player. Use this in
-- combination with the `giveTrinketsBack` function to take away and give back a trinket on the same
-- frame. This function correctly handles multiple trinket slots and ensures that all copies of the
-- trinket are removed, including smelted trinkets.
-- 
-- Note that one smelted golden trinket is the same as two smelted normal trinkets.
-- 
-- @returns Undefined if the player does not have the trinket, or TrinketSituation if they do.
function ____exports.temporarilyRemoveTrinket(self, player, trinketType)
    if not player:HasTrinket(trinketType) then
        return nil
    end
    local trinketType1 = player:GetTrinket(TrinketSlot.SLOT_1)
    local trinketType2 = player:GetTrinket(TrinketSlot.SLOT_2)
    local numTrinkets = 0
    while player:HasTrinket(trinketType) do
        player:TryRemoveTrinket(trinketType)
        numTrinkets = numTrinkets + 1
    end
    local numSmeltedTrinkets = numTrinkets
    local trinketWasInSlot1 = trinketType1 == trinketType or trinketType1 == getGoldenTrinketType(nil, trinketType)
    if trinketWasInSlot1 then
        numSmeltedTrinkets = numSmeltedTrinkets - 1
    end
    local trinketWasInSlot2 = trinketType2 == trinketType or trinketType2 == getGoldenTrinketType(nil, trinketType)
    if trinketWasInSlot2 then
        numSmeltedTrinkets = numSmeltedTrinkets - 1
    end
    return {trinketTypeRemoved = trinketType, trinketType1 = trinketType1, trinketType2 = trinketType2, numSmeltedTrinkets = numSmeltedTrinkets}
end
return ____exports
