"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeTrinketCostume = exports.removeAllPlayerTrinkets = exports.hasTrinket = exports.hasOpenTrinketSlot = exports.hasAnyTrinket = exports.getPlayersWithTrinket = exports.getPlayerTrinkets = exports.getOpenTrinketSlot = exports.anyPlayerHasTrinket = exports.addTrinketCostume = void 0;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
const cachedEnumValues_1 = require("../arrays/cachedEnumValues");
const cachedClasses_1 = require("../core/cachedClasses");
const playerIndex_1 = require("./playerIndex");
const players_1 = require("./players");
function addTrinketCostume(player, trinketType) {
    const itemConfigTrinket = cachedClasses_1.itemConfig.GetTrinket(trinketType);
    if (itemConfigTrinket === undefined) {
        return;
    }
    player.AddCostume(itemConfigTrinket, false);
}
exports.addTrinketCostume = addTrinketCostume;
/**
 * 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 anyPlayerHasTrinket(trinketType, ignoreModifiers) {
    const players = (0, playerIndex_1.getAllPlayers)();
    return players.some((player) => player.HasTrinket(trinketType, ignoreModifiers));
}
exports.anyPlayerHasTrinket = anyPlayerHasTrinket;
/**
 * 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 getOpenTrinketSlot(player) {
    const maxTrinkets = player.GetMaxTrinkets();
    const trinketType1 = player.GetTrinket(isaac_typescript_definitions_1.TrinketSlot.SLOT_1);
    const trinketType2 = player.GetTrinket(isaac_typescript_definitions_1.TrinketSlot.SLOT_2);
    if (maxTrinkets === 1) {
        return trinketType1 === isaac_typescript_definitions_1.TrinketType.NULL ? 0 : undefined;
    }
    if (maxTrinkets === 2) {
        if (trinketType1 === isaac_typescript_definitions_1.TrinketType.NULL) {
            return 0;
        }
        return trinketType2 === isaac_typescript_definitions_1.TrinketType.NULL ? 1 : undefined;
    }
    error(`The player has an unknown number of trinket slots: ${maxTrinkets}`);
}
exports.getOpenTrinketSlot = getOpenTrinketSlot;
/**
 * Helper function to get all of the trinkets that the player is currently holding. This will not
 * include any smelted trinkets.
 */
function getPlayerTrinkets(player) {
    const trinketTypes = [];
    for (const trinketSlot of cachedEnumValues_1.TRINKET_SLOT_VALUES) {
        const trinketType = player.GetTrinket(trinketSlot);
        if (trinketType !== isaac_typescript_definitions_1.TrinketType.NULL) {
            trinketTypes.push(trinketType);
        }
    }
    return trinketTypes;
}
exports.getPlayerTrinkets = getPlayerTrinkets;
/**
 * 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 getPlayersWithTrinket(...trinketTypes) {
    const players = (0, playerIndex_1.getPlayers)();
    return players.filter((player) => trinketTypes.every((trinketType) => player.HasTrinket(trinketType)));
}
exports.getPlayersWithTrinket = getPlayersWithTrinket;
/** Helper function to check to see if the player is holding one or more trinkets. */
function hasAnyTrinket(player) {
    const playerTrinketTypes = cachedEnumValues_1.TRINKET_SLOT_VALUES.map((trinketSlot) => player.GetTrinket(trinketSlot));
    return playerTrinketTypes.some((trinketType) => trinketType !== isaac_typescript_definitions_1.TrinketType.NULL);
}
exports.hasAnyTrinket = hasAnyTrinket;
/**
 * 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 hasOpenTrinketSlot(player) {
    if ((0, players_1.isCharacter)(player, isaac_typescript_definitions_1.PlayerType.SOUL_B)) {
        return false;
    }
    const openTrinketSlot = getOpenTrinketSlot(player);
    return openTrinketSlot !== undefined;
}
exports.hasOpenTrinketSlot = hasOpenTrinketSlot;
/**
 * 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 hasTrinket(player, ...trinketTypes) {
    return trinketTypes.some((trinketType) => player.HasTrinket(trinketType));
}
exports.hasTrinket = hasTrinket;
/**
 * 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 removeAllPlayerTrinkets(player) {
    for (const trinketSlot of cachedEnumValues_1.TRINKET_SLOT_VALUES) {
        const trinketType = player.GetTrinket(trinketSlot);
        if (trinketType === isaac_typescript_definitions_1.TrinketType.NULL) {
            continue;
        }
        let alreadyHasTrinket;
        do {
            player.TryRemoveTrinket(trinketType);
            alreadyHasTrinket = player.HasTrinket(trinketType);
        } while (alreadyHasTrinket);
    }
}
exports.removeAllPlayerTrinkets = removeAllPlayerTrinkets;
/**
 * 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 removeTrinketCostume(player, trinketType) {
    const itemConfigTrinket = cachedClasses_1.itemConfig.GetTrinket(trinketType);
    if (itemConfigTrinket === undefined) {
        return;
    }
    player.RemoveCostume(itemConfigTrinket);
}
exports.removeTrinketCostume = removeTrinketCostume;
