"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DisableInputs = void 0;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
const decorators_1 = require("../../../decorators");
const input_1 = require("../../../functions/input");
const ReadonlySet_1 = require("../../../types/ReadonlySet");
const Feature_1 = require("../../private/Feature");
const v = {
    run: {
        /**
         * Glowing Hour Glass support is disabled by default since it can cause bugs with extra-gameplay
         * features. (For example, whether the player should be able to move is not something that
         * should be reset by the Glowing Hour Glass.)
         */
        __ignoreGlowingHourGlass: true,
        /** Indexed by the requesting feature key. */
        disableInputs: new Map(),
        /** Indexed by the requesting feature key. */
        enableAllInputsWithBlacklistMap: new Map(),
        /** Indexed by the requesting feature key. */
        disableAllInputsWithWhitelistMap: new Map(),
    },
};
class DisableInputs extends Feature_1.Feature {
    /** @internal */
    v = v;
    /** @internal */
    constructor() {
        super();
        this.callbacksUsed = [
            // 13
            [
                isaac_typescript_definitions_1.ModCallback.INPUT_ACTION,
                this.isActionPressed,
                [isaac_typescript_definitions_1.InputHook.IS_ACTION_PRESSED], // 0
            ],
            // 13
            [
                isaac_typescript_definitions_1.ModCallback.INPUT_ACTION,
                this.isActionTriggered,
                [isaac_typescript_definitions_1.InputHook.IS_ACTION_TRIGGERED], // 1
            ],
            // 13
            [
                isaac_typescript_definitions_1.ModCallback.INPUT_ACTION,
                this.getActionValue,
                [isaac_typescript_definitions_1.InputHook.GET_ACTION_VALUE], // 2
            ],
        ];
    }
    // InputHook.IS_ACTION_PRESSED (0)
    isActionPressed = (_entity, _inputHook, buttonAction) => this.getReturnValue(buttonAction, true);
    // InputHook.IS_ACTION_TRIGGERED (1)
    isActionTriggered = (_entity, _inputHook, buttonAction) => this.getReturnValue(buttonAction, true);
    // InputHook.GET_ACTION_VALUE (2)
    getActionValue = (_entity, _inputHook, buttonAction) => this.getReturnValue(buttonAction, false);
    getReturnValue(buttonAction, booleanCallback) {
        const disableValue = booleanCallback ? false : 0;
        for (const blacklist of v.run.disableInputs.values()) {
            if (blacklist.has(buttonAction)) {
                return disableValue;
            }
        }
        for (const whitelist of v.run.disableAllInputsWithWhitelistMap.values()) {
            if (!whitelist.has(buttonAction)) {
                return disableValue;
            }
        }
        for (const blacklist of v.run.enableAllInputsWithBlacklistMap.values()) {
            if (blacklist.has(buttonAction)) {
                return disableValue;
            }
        }
        return undefined;
    }
    /**
     * Helper function to check if the `ISCFeature.DISABLE_INPUTS` feature is turned on in some
     * capacity.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @public
     */
    areInputsEnabled() {
        return (v.run.disableInputs.size === 0 &&
            v.run.enableAllInputsWithBlacklistMap.size === 0 &&
            v.run.disableAllInputsWithWhitelistMap.size === 0);
    }
    /**
     * Helper function to enable all inputs. Use this function to set things back to normal after
     * having used one of the other helper functions to disable inputs.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @public
     */
    enableAllInputs(key) {
        v.run.disableAllInputsWithWhitelistMap.delete(key);
        v.run.enableAllInputsWithBlacklistMap.delete(key);
    }
    /**
     * Helper function to disable specific inputs, like opening the console.
     *
     * This function is variadic, meaning that you can specify as many inputs as you want to disable.
     * (To disable all inputs, see the `disableAllInputs` function.
     *
     * Use the `enableAllInputs` helper function to set things back to normal.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @param buttonActions An array of the actions to action.
     * @public
     */
    disableInputs(key, ...buttonActions) {
        const buttonActionsSet = new ReadonlySet_1.ReadonlySet(buttonActions);
        v.run.disableInputs.set(key, buttonActionsSet);
    }
    /**
     * Helper function to disable all inputs. This is useful because `EntityPlayer.ControlsEnabled`
     * can be changed by the game under certain conditions.
     *
     * Use the `enableAllInputs` helper function to set things back to normal.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @public
     */
    disableAllInputs(key) {
        v.run.disableAllInputsWithWhitelistMap.set(key, new ReadonlySet_1.ReadonlySet());
        v.run.enableAllInputsWithBlacklistMap.delete(key);
    }
    /**
     * Helper function to enable all inputs besides the ones provided. This is useful because
     * `EntityPlayer.ControlsEnabled` can be changed by the game under certain conditions.
     *
     * Use the `enableAllInputs` helper function to set things back to normal.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @param blacklist A set of ButtonActions to disallow.
     * @public
     */
    enableAllInputsExceptFor(key, blacklist) {
        v.run.disableAllInputsWithWhitelistMap.delete(key);
        v.run.enableAllInputsWithBlacklistMap.set(key, blacklist);
    }
    /**
     * Helper function to disable all inputs besides the ones provided. This is useful because
     * `EntityPlayer.ControlsEnabled` can be changed by the game under certain conditions.
     *
     * Use the `enableAllInputs` helper function to set things back to normal.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @param whitelist A set of ButtonActions to allow.
     * @public
     */
    disableAllInputsExceptFor(key, whitelist) {
        v.run.disableAllInputsWithWhitelistMap.set(key, whitelist);
        v.run.enableAllInputsWithBlacklistMap.delete(key);
    }
    /**
     * Helper function to disable only the inputs used for moving the character (or moving the cursor
     * in the UI). This is useful because `EntityPlayer.ControlsEnabled` can be changed by the game
     * under certain conditions.
     *
     * Use the `enableAllInputs` helper function to set things back to normal.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @public
     */
    disableMovementInputs(key) {
        this.enableAllInputsExceptFor(key, input_1.MOVEMENT_BUTTON_ACTIONS_SET);
    }
    /**
     * Helper function to disable only the inputs used for shooting tears. This is useful because
     * `EntityPlayer.ControlsEnabled` can be changed by the game under certain conditions.
     *
     * Use the `enableAllInputs` helper function to set things back to normal.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.DISABLE_INPUTS`.
     *
     * @param key The name of the mod feature that is requesting the enable/disable. For example, if
     *            this was part of the code for a custom enemy called "Super Gaper", then you could
     *            use a key of "SuperGaper". The name is necessary so that multiple mod features can
     *            work in tandem.
     * @public
     */
    disableShootingInputs(key) {
        this.enableAllInputsExceptFor(key, input_1.SHOOTING_BUTTON_ACTIONS_SET);
    }
}
exports.DisableInputs = DisableInputs;
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "areInputsEnabled", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "enableAllInputs", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "disableInputs", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "disableAllInputs", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "enableAllInputsExceptFor", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "disableAllInputsExceptFor", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "disableMovementInputs", null);
__decorate([
    decorators_1.Exported
], DisableInputs.prototype, "disableShootingInputs", null);
