"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const color_1 = require("../color");
const yok_1 = require("../common/yok");
class KeyCommandHelper {
    constructor() {
        this.platform = "all";
        this.overrides = {};
        this.onKeyPressed = (data) => __awaiter(this, void 0, void 0, function* () {
            const key = data.toString();
            // Allow Ctrl + C always.
            if (this.keyCommandExecutionBlocked && key !== "\u0003" /* SpecialKeys.CtrlC */)
                return;
            try {
                const exists = yok_1.injector.getRegisteredKeyCommandsNames().includes(key);
                if (exists) {
                    const keyCommand = yok_1.injector.resolveKeyCommand(key);
                    if (keyCommand.platform === "all" ||
                        keyCommand.platform === this.platform ||
                        this.platform === "all") {
                        if (keyCommand.canExecute &&
                            !keyCommand.canExecute(this.processType)) {
                            console.log("blocked execution");
                            return;
                        }
                        if (keyCommand.willBlockKeyCommandExecution)
                            this.keyCommandExecutionBlocked = true;
                        if (this.overrides[key]) {
                            if (!(yield this.overrides[key]())) {
                                this.keyCommandExecutionBlocked = false;
                                process.stdin.resume();
                                return;
                            }
                        }
                        if (keyCommand.key !== "\u0003" /* SpecialKeys.CtrlC */) {
                            const line = ` ${color_1.color.dim("→")} ${color_1.color.bold(keyCommand.key)} — ${keyCommand.description}`;
                            const lineLength = (0, color_1.stripColors)(line).length - 1;
                            console.log(color_1.color.dim(` ┌${"─".repeat(lineLength)}┐`));
                            console.log(line + color_1.color.dim(" │"));
                            console.log(color_1.color.dim(` └${"─".repeat(lineLength)}┘`));
                            console.log("");
                        }
                        const result = yield keyCommand.execute(this.platform);
                        this.keyCommandExecutionBlocked = false;
                        if (process.stdin.setRawMode) {
                            process.stdin.resume();
                        }
                        return result;
                    }
                }
                process.stdout.write(key);
            }
            catch (e) {
                const $logger = yok_1.injector.resolve("logger");
                $logger.error(e.message);
            }
        });
    }
    addOverride(key, execute) {
        this.overrides[key] = execute;
    }
    removeOverride(key) {
        this.overrides[key] = undefined;
    }
    printCommands(platform) {
        const commands = yok_1.injector.getRegisteredKeyCommandsNames();
        const commandHelp = commands.reduce((arr, key) => {
            const command = yok_1.injector.resolveKeyCommand(key);
            if (!command.description ||
                (command.platform !== "all" &&
                    command.platform !== platform &&
                    platform !== "all") ||
                (command.canExecute && !command.canExecute(this.processType))) {
                return arr;
            }
            else {
                arr.push(`   ${color_1.color.bold(command.key)} — ${command.description}`);
                return arr;
            }
        }, []);
        console.info([
            "",
            `  The CLI is ${color_1.color.underline(`interactive`)}, you can press the following keys any time (make sure the terminal has focus).`,
            "",
            ...commandHelp,
            "",
        ].join("\n"));
    }
    attachKeyCommands(platform, processType) {
        this.processType = processType;
        this.platform = platform;
        const stdin = process.stdin;
        if (!stdin.setRawMode) {
            process.on("message", (key) => {
                this.onKeyPressed(Buffer.from(key));
            });
        }
        else {
            stdin.setRawMode(false);
            stdin.setRawMode(true);
            stdin.resume();
            stdin.on("data", this.onKeyPressed);
        }
    }
    detachKeyCommands() {
        process.stdin.off("data", this.onKeyPressed);
        process.stdin.setRawMode(false);
    }
}
exports.default = KeyCommandHelper;
yok_1.injector.register("keyCommandHelper", KeyCommandHelper);
//# sourceMappingURL=key-command-helper.js.map