"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.CustomHotkeys = void 0;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
const decorators_1 = require("../../../decorators");
const input_1 = require("../../../functions/input");
const DefaultMap_1 = require("../../DefaultMap");
const Feature_1 = require("../../private/Feature");
class CustomHotkeys extends Feature_1.Feature {
    /**
     * The keys are the keyboard keys that trigger the hotkey. The values are the functions that
     * contain the arbitrary code to run.
     */
    staticHotkeyFunctionMap = new Map();
    /**
     * The keys are the functions that determine what the hotkey key is. The values are the functions
     * that contain the arbitrary code to run.
     */
    dynamicHotkeyFunctionMap = new Map();
    keyPressedMap = new DefaultMap_1.DefaultMap(false);
    /** @internal */
    constructor() {
        super();
        this.callbacksUsed = [
            // 2
            [isaac_typescript_definitions_1.ModCallback.POST_RENDER, this.postRender],
        ];
    }
    // ModCallback.POST_RENDER (2)
    postRender = () => {
        for (const [keyboard, triggerFunc] of this.staticHotkeyFunctionMap) {
            this.checkIfTriggered(keyboard, triggerFunc);
        }
        for (const [keyboardFunc, triggerFunc] of this.dynamicHotkeyFunctionMap) {
            const keyboard = keyboardFunc();
            if (keyboard !== undefined) {
                this.checkIfTriggered(keyboard, triggerFunc);
            }
        }
    };
    checkIfTriggered(keyboard, triggerFunc) {
        const isPressed = (0, input_1.isKeyboardPressed)(keyboard);
        const wasPreviouslyPressed = this.keyPressedMap.getAndSetDefault(keyboard);
        this.keyPressedMap.set(keyboard, isPressed);
        if (isPressed && !wasPreviouslyPressed) {
            triggerFunc();
        }
    }
    /**
     * Helper function to run arbitrary code when you press and release a specific keyboard key.
     *
     * This can be used to easily set up custom hotkeys to facilitate custom game features or to
     * assist in debugging.
     *
     * Inputs are checked for in the `POST_RENDER` callback.
     *
     * This is different from the `setHotkey` function in that the keyboard activation key is not
     * hardcoded and is instead the return value of a provided function. This is useful for situations
     * where the key can change (like if end-users can specify a custom hotkey using Mod Config Menu).
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.CUSTOM_HOTKEYS`.
     *
     * @param getKeyFunc The function that returns the key that will trigger the hotkey.
     * @param triggerFunc A function containing the arbitrary code that you want to execute when the
     *                    hotkey is triggered.
     * @public
     */
    setConditionalHotkey(getKeyFunc, triggerFunc) {
        if (this.dynamicHotkeyFunctionMap.has(getKeyFunc)) {
            error("Failed to register a hotkey due to a custom hotkey already being defined for the submitted function.");
        }
        this.dynamicHotkeyFunctionMap.set(getKeyFunc, triggerFunc);
    }
    /**
     * Helper function to run arbitrary code when you press and release a specific keyboard key.
     *
     * This can be used to easily set up custom hotkeys to facilitate custom game features or to
     * assist in debugging.
     *
     * Inputs are checked for in the `POST_RENDER` callback.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.CUSTOM_HOTKEYS`.
     *
     * @param keyboard The key that you want to trigger the hotkey.
     * @param triggerFunc A function containing the arbitrary code that you want to execute when the
     *                    hotkey is triggered.
     * @public
     */
    setHotkey(keyboard, triggerFunc) {
        if (this.staticHotkeyFunctionMap.has(keyboard)) {
            error(`Failed to register a hotkey due to a hotkey already being defined for: Keyboard.${isaac_typescript_definitions_1.Keyboard[keyboard]} (${keyboard})`);
        }
        this.staticHotkeyFunctionMap.set(keyboard, triggerFunc);
    }
    /**
     * Helper function to remove a hotkey created with the `setConditionalHotkey` function.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.CUSTOM_HOTKEYS`.
     *
     * @param getKeyFunc Equal to the `getKeyFunc` that you passed when initially registering the
     *                   hotkey.
     * @public
     */
    unsetConditionalHotkey(getKeyFunc) {
        if (!this.dynamicHotkeyFunctionMap.has(getKeyFunc)) {
            error("Failed to unregister a hotkey since there is no existing hotkey defined for the submitted function.");
        }
        this.dynamicHotkeyFunctionMap.delete(getKeyFunc);
    }
    /**
     * Helper function to remove a hotkey created with the `setHotkey` function.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.CUSTOM_HOTKEYS`.
     *
     * @param keyboard Equal to the keyboard value that you passed when initially registering the
     *                 hotkey.
     * @public
     */
    unsetHotkey(keyboard) {
        if (!this.staticHotkeyFunctionMap.has(keyboard)) {
            error(`Failed to unregister a hotkey since there is no existing hotkey defined for: Keyboard.${isaac_typescript_definitions_1.Keyboard[keyboard]} (${keyboard})`);
        }
        this.staticHotkeyFunctionMap.delete(keyboard);
    }
}
exports.CustomHotkeys = CustomHotkeys;
__decorate([
    decorators_1.Exported
], CustomHotkeys.prototype, "setConditionalHotkey", null);
__decorate([
    decorators_1.Exported
], CustomHotkeys.prototype, "setHotkey", null);
__decorate([
    decorators_1.Exported
], CustomHotkeys.prototype, "unsetConditionalHotkey", null);
__decorate([
    decorators_1.Exported
], CustomHotkeys.prototype, "unsetHotkey", null);
