"use strict";
/*
 * Copyright 2016 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.isMac = exports.normalizeKeyCombo = exports.getKeyCombo = exports.getKeyComboString = exports.parseKeyCombo = exports.comboMatches = exports.SHIFT_KEYS = exports.CONFIG_ALIASES = exports.MODIFIER_BIT_MASKS = void 0;
/**
 * Named modifier keys
 *
 * @see https://www.w3.org/TR/uievents-key/#keys-modifier
 */
var MODIFIER_KEYS = new Set(["Shift", "Control", "Alt", "Meta"]);
exports.MODIFIER_BIT_MASKS = {
    alt: 1,
    ctrl: 2,
    meta: 4,
    shift: 8,
};
exports.CONFIG_ALIASES = {
    cmd: "meta",
    command: "meta",
    del: "delete",
    esc: "escape",
    escape: "escape",
    minus: "-",
    mod: isMac(undefined) ? "meta" : "ctrl",
    option: "alt",
    plus: "+",
    return: "enter",
    win: "meta",
    // need these aliases for backwards-compatibility (but they're also convenient)
    up: "ArrowUp",
    left: "ArrowLeft",
    down: "ArrowDown",
    right: "ArrowRight",
};
/**
 * Key mapping used in getKeyCombo() implementation for physical keys which are not alphabet characters or digits.
 *
 * N.B. at some point, we should stop using this mapping, since we can implement the desired functionality in a more
 * straightforward way by using the `event.code` property, which will always tell us the identifiers represented by the
 * _values_ in this object (the default physical keys, unaltered by modifier keys or keyboard layout).
 */
exports.SHIFT_KEYS = {
    "~": "`",
    _: "-",
    "+": "=",
    "{": "[",
    "}": "]",
    "|": "\\",
    ":": ";",
    '"': "'",
    "<": ",",
    ">": ".",
    "?": "/",
};
function comboMatches(a, b) {
    return a.modifiers === b.modifiers && a.key === b.key;
}
exports.comboMatches = comboMatches;
/**
 * Converts a key combo string into a key combo object. Key combos include
 * zero or more modifier keys, such as `shift` or `alt`, and exactly one
 * action key, such as `A`, `enter`, or `left`.
 *
 * For action keys that require a shift, e.g. `@` or `|`, we inlude the
 * necessary `shift` modifier and automatically convert the action key to the
 * unshifted version. For example, `@` is equivalent to `shift+2`.
 */
var parseKeyCombo = function (combo) {
    var pieces = combo.replace(/\s/g, "").toLowerCase().split("+");
    var modifiers = 0;
    var key;
    for (var _i = 0, pieces_1 = pieces; _i < pieces_1.length; _i++) {
        var piece = pieces_1[_i];
        if (piece === "") {
            throw new Error("Failed to parse key combo \"".concat(combo, "\".\n                Valid key combos look like \"cmd + plus\", \"shift+p\", or \"!\""));
        }
        if (exports.CONFIG_ALIASES[piece] !== undefined) {
            piece = exports.CONFIG_ALIASES[piece];
        }
        if (exports.MODIFIER_BIT_MASKS[piece] !== undefined) {
            modifiers += exports.MODIFIER_BIT_MASKS[piece];
        }
        else if (exports.SHIFT_KEYS[piece] !== undefined) {
            modifiers += exports.MODIFIER_BIT_MASKS.shift;
            key = exports.SHIFT_KEYS[piece];
        }
        else {
            key = piece.toLowerCase();
        }
    }
    return { modifiers: modifiers, key: key };
};
exports.parseKeyCombo = parseKeyCombo;
/**
 * Interprets a keyboard event as a valid KeyComboTag `combo` prop string value.
 *
 * Note that this function is only used in the docs example and tests; it is not used by `useHotkeys()` or any
 * Blueprint consumers that we are currently aware of.
 */
var getKeyComboString = function (e) {
    var comboParts = [];
    // modifiers first
    if (e.ctrlKey) {
        comboParts.push("ctrl");
    }
    if (e.altKey) {
        comboParts.push("alt");
    }
    if (e.shiftKey) {
        comboParts.push("shift");
    }
    if (e.metaKey) {
        comboParts.push("meta");
    }
    var key = maybeGetKeyFromEventCode(e);
    if (key !== undefined) {
        comboParts.push(key);
    }
    else {
        if (e.code === "Space") {
            comboParts.push("space");
        }
        else if (MODIFIER_KEYS.has(e.key)) {
            // do nothing
        }
        else if (e.shiftKey && exports.SHIFT_KEYS[e.key] !== undefined) {
            comboParts.push(exports.SHIFT_KEYS[e.key]);
        }
        else if (e.key !== undefined) {
            comboParts.push(e.key.toLowerCase());
        }
    }
    return comboParts.join(" + ");
};
exports.getKeyComboString = getKeyComboString;
var KEY_CODE_PREFIX = "Key";
var DIGIT_CODE_PREFIX = "Digit";
function maybeGetKeyFromEventCode(e) {
    if (e.code == null) {
        return undefined;
    }
    if (e.code.startsWith(KEY_CODE_PREFIX)) {
        // Code looks like "KeyA", etc.
        return e.code.substring(KEY_CODE_PREFIX.length).toLowerCase();
    }
    else if (e.code.startsWith(DIGIT_CODE_PREFIX)) {
        // Code looks like "Digit1", etc.
        return e.code.substring(DIGIT_CODE_PREFIX.length).toLowerCase();
    }
    else if (e.code === "Space") {
        return "space";
    }
    return undefined;
}
/**
 * Determines the key combo object from the given keyboard event. A key combo includes zero or more modifiers
 * (represented by a bitmask) and one physical key. For most keys, we prefer dealing with the `code` property of the
 * event, since this is not altered by keyboard layout or the state of modifier keys. Fall back to using the `key`
 * property.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
 */
var getKeyCombo = function (e) {
    var _a, _b;
    var key;
    if (MODIFIER_KEYS.has(e.key)) {
        // Leave local variable `key` undefined
    }
    else {
        key = (_a = maybeGetKeyFromEventCode(e)) !== null && _a !== void 0 ? _a : (_b = e.key) === null || _b === void 0 ? void 0 : _b.toLowerCase();
    }
    var modifiers = 0;
    if (e.altKey) {
        modifiers += exports.MODIFIER_BIT_MASKS.alt;
    }
    if (e.ctrlKey) {
        modifiers += exports.MODIFIER_BIT_MASKS.ctrl;
    }
    if (e.metaKey) {
        modifiers += exports.MODIFIER_BIT_MASKS.meta;
    }
    if (e.shiftKey) {
        modifiers += exports.MODIFIER_BIT_MASKS.shift;
        if (exports.SHIFT_KEYS[e.key] !== undefined) {
            key = exports.SHIFT_KEYS[e.key];
        }
    }
    return { modifiers: modifiers, key: key };
};
exports.getKeyCombo = getKeyCombo;
/**
 * Splits a key combo string into its constituent key values and looks up
 * aliases, such as `return` -> `enter`.
 *
 * Unlike the parseKeyCombo method, this method does NOT convert shifted
 * action keys. So `"@"` will NOT be converted to `["shift", "2"]`).
 */
var normalizeKeyCombo = function (combo, platformOverride) {
    var keys = combo.replace(/\s/g, "").split("+");
    return keys.map(function (key) {
        var keyName = exports.CONFIG_ALIASES[key] != null ? exports.CONFIG_ALIASES[key] : key;
        return keyName === "meta" ? (isMac(platformOverride) ? "cmd" : "ctrl") : keyName;
    });
};
exports.normalizeKeyCombo = normalizeKeyCombo;
function isMac(platformOverride) {
    // HACKHACK: see https://github.com/palantir/blueprint/issues/5174
    // eslint-disable-next-line @typescript-eslint/no-deprecated
    var platform = platformOverride !== null && platformOverride !== void 0 ? platformOverride : (typeof navigator !== "undefined" ? navigator.platform : undefined);
    return platform === undefined ? false : /Mac|iPod|iPhone|iPad/.test(platform);
}
exports.isMac = isMac;
//# sourceMappingURL=hotkeyParser.js.map