"use strict";
/**
 * Consider the following code that uses a number enum:
 *
 * ```ts
 * enum MyEnum {
 *   Value1,
 * }
 *
 * function asMyEnum(num: number): MyEnum {}
 *
 * declare const something: unknown;
 *
 * const foo = something as MyEnum; // no error
 * const bar: MyEnum = something; // error
 * const baz = asMyEnum(something); // error
 * ```
 *
 * Here, using `as` does not give an error because TypeScript allows you to assert a type to a
 * supertype or a subtype. Thus, using `as` to perform a type assertion is not as safe as using a
 * variable declaration or a helper function. However, if we use a variable declaration, then the
 * `isaacscript/strict-enums` rule is triggered, which requires suppressing the lint rule with a `//
 * eslint-disable-next-line`. Thus, the safest and more concise way to do a type assertion is to use
 * a helper function.
 *
 * This file contains helper functions for various number enums that might require type assertions.
 * It also contains helper functions for run-time type checks.
 *
 * @module
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseIntSafe = exports.isUserdata = exports.isTable = exports.isString = exports.isPrimitive = exports.isNumber = exports.isInteger = exports.isFunction = exports.isBoolean = exports.asTrinketType = exports.asString = exports.asRoomType = exports.asPlayerType = exports.asPillEffect = exports.asPillColor = exports.asNumber = exports.asNPCState = exports.asLevelStage = exports.asInt = exports.asFloat = exports.asCollectibleType = exports.asCardType = void 0;
/**
 * Helper function to safely cast an `int` to a `CardType`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asCardType(num) {
    return num;
}
exports.asCardType = asCardType;
/**
 * Helper function to safely cast an `int` to a `CollectibleType`. (This is better than using the
 * `as` TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asCollectibleType(num) {
    return num;
}
exports.asCollectibleType = asCollectibleType;
/**
 * Helper function to safely cast an enum to an `int`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asFloat(num) {
    return num;
}
exports.asFloat = asFloat;
/**
 * Helper function to safely cast an enum to an `int`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asInt(num) {
    return num;
}
exports.asInt = asInt;
/**
 * Helper function to safely cast an `int` to a `LevelStage`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asLevelStage(num) {
    return num;
}
exports.asLevelStage = asLevelStage;
/**
 * Helper function to safely cast an `int` to a `NPCState`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asNPCState(num) {
    return num;
}
exports.asNPCState = asNPCState;
/**
 * Helper function to safely cast an enum to a `number`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asNumber(num) {
    return num;
}
exports.asNumber = asNumber;
/**
 * Helper function to safely cast an `int` to a `PillColor`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asPillColor(num) {
    return num;
}
exports.asPillColor = asPillColor;
/**
 * Helper function to safely cast an `int` to a `PillEffect`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asPillEffect(num) {
    return num;
}
exports.asPillEffect = asPillEffect;
/**
 * Helper function to safely cast an `int` to a `PlayerType`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asPlayerType(num) {
    return num;
}
exports.asPlayerType = asPlayerType;
/**
 * Helper function to safely cast an `int` to a `RoomType`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asRoomType(num) {
    return num;
}
exports.asRoomType = asRoomType;
/**
 * Helper function to safely cast an enum to a `string`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asString(str) {
    return str;
}
exports.asString = asString;
/**
 * Helper function to safely cast an `int` to a `TrinketType`. (This is better than using the `as`
 * TypeScript keyword to do a type assertion, since that can obfuscate compiler errors. )
 *
 * This is useful to satisfy the "isaacscript/strict-enums" ESLint rule.
 */
function asTrinketType(num) {
    return num;
}
exports.asTrinketType = asTrinketType;
function isBoolean(variable) {
    return type(variable) === "boolean";
}
exports.isBoolean = isBoolean;
// eslint-disable-next-line @typescript-eslint/ban-types
function isFunction(variable) {
    return type(variable) === "function";
}
exports.isFunction = isFunction;
function isInteger(variable) {
    if (!isNumber(variable)) {
        return false;
    }
    return variable === Math.floor(variable);
}
exports.isInteger = isInteger;
function isNumber(variable) {
    return type(variable) === "number";
}
exports.isNumber = isNumber;
/** Helper function to detect if a variable is a boolean, number, or string. */
function isPrimitive(variable) {
    const variableType = type(variable);
    return (variableType === "boolean" ||
        variableType === "number" ||
        variableType === "string");
}
exports.isPrimitive = isPrimitive;
function isString(variable) {
    return type(variable) === "string";
}
exports.isString = isString;
function isTable(variable) {
    return type(variable) === "table";
}
exports.isTable = isTable;
function isUserdata(variable) {
    return type(variable) === "userdata";
}
exports.isUserdata = isUserdata;
/**
 * Helper function to convert a string to an integer. Returns undefined if the string is not an
 * integer.
 *
 * Under the hood, this uses the built-in `tonumber` and `math.floor` functions.
 *
 * This is named `parseIntSafe` in order to match the helper function in `isaacscript-common-ts`.
 */
function parseIntSafe(string) {
    if (!isString(string)) {
        return undefined;
    }
    // - The `tonumber` function correctly deals with leading and trailing whitespace.
    // - The `tonumber` function correctly deals with a mix of numbers and letters. (e.g. `1a` returns
    //   undefined.)
    const number = tonumber(string);
    if (number === undefined) {
        return undefined;
    }
    const flooredNumber = math.floor(number);
    return number === flooredNumber ? flooredNumber : undefined;
}
exports.parseIntSafe = parseIntSafe;
