"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.trinketHasCacheFlag = exports.setTrinketSprite = exports.newTrinketSprite = exports.isVanillaTrinketType = exports.isValidTrinketType = exports.isModdedTrinketType = exports.isGoldenTrinketType = exports.getTrinketName = exports.getTrinketGfxFilename = exports.getTrinketDescription = exports.getNormalTrinketType = exports.getMysteriousPaperEffectForFrame = exports.getGoldenTrinketType = void 0;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
const cachedClasses_1 = require("../core/cachedClasses");
const constants_1 = require("../core/constants");
const constantsFirstLast_1 = require("../core/constantsFirstLast");
const MysteriousPaperEffect_1 = require("../enums/MysteriousPaperEffect");
const trinketDescriptions_1 = require("../objects/trinketDescriptions");
const trinketNames_1 = require("../objects/trinketNames");
const entities_1 = require("./entities");
const enums_1 = require("./enums");
const flag_1 = require("./flag");
const pickupVariants_1 = require("./pickupVariants");
const sprites_1 = require("./sprites");
const types_1 = require("./types");
/**
 * Add this to a `TrinketType` to get the corresponding golden trinket type.
 *
 * Corresponds to the vanilla `PillColor.TRINKET_GOLDEN_FLAG` value.
 *
 * 1 << 15
 */
const GOLDEN_TRINKET_ADJUSTMENT = 32_768;
const NUM_MYSTERIOUS_PAPER_EFFECTS = (0, enums_1.getEnumLength)(MysteriousPaperEffect_1.MysteriousPaperEffect);
const TRINKET_ANM2_PATH = "gfx/005.350_trinket.anm2";
const 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 getGoldenTrinketType(trinketType) {
    return isGoldenTrinketType(trinketType)
        ? trinketType
        : trinketType + GOLDEN_TRINKET_ADJUSTMENT;
}
exports.getGoldenTrinketType = getGoldenTrinketType;
/**
 * 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 getMysteriousPaperEffectForFrame(player, frameCount) {
    if (frameCount === undefined) {
        frameCount = player.FrameCount;
    }
    if (!player.HasTrinket(isaac_typescript_definitions_1.TrinketType.MYSTERIOUS_PAPER)) {
        return undefined;
    }
    return frameCount % NUM_MYSTERIOUS_PAPER_EFFECTS;
}
exports.getMysteriousPaperEffectForFrame = getMysteriousPaperEffectForFrame;
/**
 * 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 getNormalTrinketType(trinketType) {
    return isGoldenTrinketType(trinketType)
        ? trinketType - GOLDEN_TRINKET_ADJUSTMENT
        : trinketType;
}
exports.getNormalTrinketType = getNormalTrinketType;
/**
 * 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 getTrinketDescription(trinketType) {
    // "ItemConfigItem.Description" is bugged with vanilla items on patch v1.7.6, so we use a
    // hard-coded object as a workaround.
    const trinketDescription = trinketDescriptions_1.TRINKET_DESCRIPTIONS[trinketType];
    if (trinketDescription !== undefined) {
        return trinketDescription;
    }
    const itemConfigItem = cachedClasses_1.itemConfig.GetTrinket(trinketType);
    if (itemConfigItem !== undefined) {
        return itemConfigItem.Description;
    }
    return trinketDescriptions_1.DEFAULT_TRINKET_DESCRIPTION;
}
exports.getTrinketDescription = getTrinketDescription;
/**
 * 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 getTrinketGfxFilename(trinketType) {
    const itemConfigItem = cachedClasses_1.itemConfig.GetTrinket(trinketType);
    if (itemConfigItem === undefined) {
        return constants_1.BLIND_ITEM_PNG_PATH;
    }
    return itemConfigItem.GfxFileName;
}
exports.getTrinketGfxFilename = getTrinketGfxFilename;
/**
 * 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 getTrinketName(trinketType) {
    // "ItemConfigItem.Name" is bugged with vanilla items on patch v1.7.6, so we use a hard-coded
    // object as a workaround.
    const trinketName = trinketNames_1.TRINKET_NAMES[trinketType];
    if (trinketName !== undefined) {
        return trinketName;
    }
    const itemConfigItem = cachedClasses_1.itemConfig.GetTrinket(trinketType);
    if (itemConfigItem !== undefined) {
        return itemConfigItem.Name;
    }
    return trinketNames_1.DEFAULT_TRINKET_NAME;
}
exports.getTrinketName = getTrinketName;
function isGoldenTrinketType(trinketType) {
    return (0, types_1.asNumber)(trinketType) > GOLDEN_TRINKET_ADJUSTMENT;
}
exports.isGoldenTrinketType = isGoldenTrinketType;
function isModdedTrinketType(trinketType) {
    return !isVanillaTrinketType(trinketType);
}
exports.isModdedTrinketType = isModdedTrinketType;
function isValidTrinketType(trinketType) {
    const potentialTrinketType = (0, types_1.asTrinketType)(trinketType);
    const itemConfigItem = cachedClasses_1.itemConfig.GetTrinket(potentialTrinketType);
    return itemConfigItem !== undefined;
}
exports.isValidTrinketType = isValidTrinketType;
function isVanillaTrinketType(trinketType) {
    return trinketType <= constantsFirstLast_1.LAST_VANILLA_TRINKET_TYPE;
}
exports.isVanillaTrinketType = isVanillaTrinketType;
/**
 * 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 newTrinketSprite(trinketType) {
    const sprite = Sprite();
    sprite.Load(TRINKET_ANM2_PATH, false);
    const gfxFileName = getTrinketGfxFilename(trinketType);
    sprite.ReplaceSpritesheet(TRINKET_SPRITE_LAYER, gfxFileName);
    sprite.LoadGraphics();
    const defaultAnimation = sprite.GetDefaultAnimation();
    sprite.Play(defaultAnimation, true);
    return sprite;
}
exports.newTrinketSprite = newTrinketSprite;
/**
 * 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 setTrinketSprite(trinket, pngPath) {
    if (!(0, pickupVariants_1.isTrinket)(trinket)) {
        const entityID = (0, entities_1.getEntityID)(trinket);
        error(`The "setTrinketSprite" function was given a non-trinket: ${entityID}`);
    }
    const sprite = trinket.GetSprite();
    if (pngPath === undefined) {
        // We use `clearSpriteLayer` instead of `Sprite.Reset` to maintain parity with the
        // `setCollectibleSprite` function.
        (0, sprites_1.clearSprite)(sprite);
    }
    else {
        sprite.ReplaceSpritesheet(TRINKET_SPRITE_LAYER, pngPath);
        sprite.LoadGraphics();
    }
}
exports.setTrinketSprite = setTrinketSprite;
/** Helper function to check in the item config if a given trinket has a given cache flag. */
function trinketHasCacheFlag(trinketType, cacheFlag) {
    const itemConfigItem = cachedClasses_1.itemConfig.GetTrinket(trinketType);
    if (itemConfigItem === undefined) {
        return false;
    }
    return (0, flag_1.hasFlag)(itemConfigItem.CacheFlags, cacheFlag);
}
exports.trinketHasCacheFlag = trinketHasCacheFlag;
