"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeFlag = exports.isSelfDamage = exports.isEmptyFlag = exports.hasFlag = exports.getFlagName = exports.bitFlags = exports.addFlag = void 0;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
/**
 * Helper function to add a bit flag to an existing set of bit flags.
 *
 * This is a variadic function, so pass as many flags as you want to add.
 *
 * Example 1:
 *
 * ```ts
 * // Give the player spectral tears
 * const player = Isaac.GetPlayer();
 * player.TearFlags = addFlag(player.TearFlags, TearFlags.TEAR_SPECTRAL);
 * ```
 *
 * Example 2:
 *
 * ```ts
 * // Give the player spectral and homing tears
 * const player = Isaac.GetPlayer();
 * player.TearFlags = addFlag(player.TearFlags, TearFlags.TEAR_SPECTRAL, TearFlags.TEAR_HOMING);
 * ```
 *
 * @param flags The existing set of bit flags.
 * @param flagsToAdd One or more bit flags to add, each as a separate argument.
 * @returns The combined bit flags.
 */
function addFlag(flags, ...flagsToAdd) {
    let flagsAsInt = flags;
    for (const flagToAdd of flagsToAdd) {
        flagsAsInt |= flagToAdd;
    }
    return flagsAsInt;
}
exports.addFlag = addFlag;
/**
 * Helper function for casting a flag enum value to a `BitFlags` object.
 *
 * This is useful because the compiler will prevent you from assigning a specific flag to a
 * `BitFlags` field. (It does this to ensure type safety, since `BitFlags` can represent a zero
 * value or a composition of N flags.)
 *
 * For example:
 *
 * ```ts
 * player.TearFlags = bitFlags(TearFlag.SPECTRAL);
 * ```
 */
function bitFlags(flag) {
    return flag;
}
exports.bitFlags = bitFlags;
/**
 * Helper function to get the key associated with a particular flag.
 *
 * (Since bit flags are represented by custom objects instead of normal TypeScript enums, you cannot
 * use the reverse mapping to find the associated key of a given enum value. Use this helper
 * function instead of indexing the enum directly.)
 */
function getFlagName(flag, flagEnum) {
    for (const [key, value] of Object.entries(flagEnum)) {
        if (value === flag) {
            return key;
        }
    }
    return undefined;
}
exports.getFlagName = getFlagName;
/**
 * Helper function to determine if a particular bit flag is set to true.
 *
 * This is a variadic function, so pass as many flags as you want to check for. If passed multiple
 * flags, it will only return true if all of the flags are set.
 *
 * For example:
 *
 * ```ts
 * const player = Isaac.GetPlayer();
 * if (hasFlag(player.TearFlags, TearFlags.TEAR_SPECTRAL) {
 *   // The player currently has spectral tears
 * }
 * ```
 *
 * @param flags The existing set of bit flags.
 * @param flagsToCheck One or more bit flags to check for, each as a separate argument.
 */
function hasFlag(flags, ...flagsToCheck) {
    const flagsAsInt = flags;
    for (const flagToCheck of flagsToCheck) {
        if (!((flagsAsInt & flagToCheck) === flagToCheck)) {
            return false;
        }
    }
    return true;
}
exports.hasFlag = hasFlag;
/**
 * Helper function to check if every bit in the flag is turned off.
 *
 * (This is equivalent to checking if the flag is equal to 0, but this is not possible without
 * casting the flag to a number.)
 */
function isEmptyFlag(flag) {
    return flag === 0;
}
exports.isEmptyFlag = isEmptyFlag;
/**
 * Helper function to determine whether damage to a player in the `ENTITY_TAKE_DMG` callback was
 * self-inflicted. For example, damage from a Curse Room door, a Razor, or a Blood Donation Machine
 * would count as self-inflicted damage.
 */
function isSelfDamage(damageFlags) {
    return (
    // Exclude self-damage from e.g. Curse Room door spikes.
    hasFlag(damageFlags, isaac_typescript_definitions_1.DamageFlag.NO_PENALTIES) ||
        // Exclude self-damage from e.g. Razor.
        hasFlag(damageFlags, isaac_typescript_definitions_1.DamageFlag.RED_HEARTS));
}
exports.isSelfDamage = isSelfDamage;
/**
 * Helper function to remove a bit flag from an existing set of bit flags.
 *
 * This is a variadic function, so pass as many flags as you want to remove.
 *
 * For example:
 *
 * ```ts
 * // Remove spectral tears from the player, if present
 * const player = Isaac.GetPlayer();
 * player.TearFlags = removeFlag(player.TearFlags, TearFlags.TEAR_SPECTRAL);
 * ```
 *
 * @param flags The existing set of bit flags.
 * @param flagsToRemove One or more bit flags to remove, each as a separate argument.
 * @returns The combined bit flags.
 */
function removeFlag(flags, ...flagsToRemove) {
    let flagsAsInt = flags;
    for (const flagToRemove of flagsToRemove) {
        flagsAsInt &= ~flagToRemove;
    }
    return flagsAsInt;
}
exports.removeFlag = removeFlag;
