"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InputRouter = void 0;
const types_1 = require("./types");
class InputRouter {
    onToggle;
    onChildInput;
    onGameInput;
    getFocus;
    onScroll;
    isMouseIntercepted;
    toggleKey;
    modifierKey;
    constructor(onToggle, onChildInput, onGameInput, getFocus, onScroll, isMouseIntercepted, toggleKey = 'ctrl+]', modifierKey = 'ctrl') {
        this.onToggle = onToggle;
        this.onChildInput = onChildInput;
        this.onGameInput = onGameInput;
        this.getFocus = getFocus;
        this.onScroll = onScroll;
        this.isMouseIntercepted = isMouseIntercepted;
        this.toggleKey = toggleKey;
        this.modifierKey = modifierKey;
    }
    setToggleKey(key) {
        this.toggleKey = key;
    }
    setModifierKey(key) {
        this.modifierKey = key;
    }
    start() {
        if (process.stdin.isTTY)
            process.stdin.setRawMode(true);
        process.stdin.resume();
        process.stdin.on('data', this.handleData);
    }
    stop() {
        process.stdin.removeListener('data', this.handleData);
        try {
            if (process.stdin.isTTY) {
                process.stdin.setRawMode(false);
            }
            process.stdin.pause();
        }
        catch {
            // May already be closed
        }
    }
    handleData = (data) => {
        if (this.checkSingleKeyToggle(data)) {
            this.onToggle();
            return;
        }
        if (this.isMouseIntercepted() && this.consumeMouseEvent(data))
            return;
        this.forwardInput(data);
    };
    consumeMouseEvent(data) {
        const s = data.toString('utf8');
        if (!s.startsWith('\x1b[<'))
            return false;
        const regex = /\x1b\[<(\d+);\d+;\d+[Mm]/g;
        for (const match of s.matchAll(regex)) {
            const button = parseInt(match[1]);
            if (button === 64)
                this.onScroll(-3);
            else if (button === 65)
                this.onScroll(3);
        }
        return true;
    }
    checkSingleKeyToggle(data) {
        if (this.toggleKey === 'f12' && data.toString('utf8') === '\x1b[24~')
            return true;
        if (this.toggleKey === 'ctrl+]' && data.length === 1 && data[0] === 0x1d)
            return true;
        return false;
    }
    forwardInput(data) {
        const focus = this.getFocus();
        if (focus === types_1.InputFocus.CHILD) {
            this.onChildInput(data);
        }
        else {
            const key = this.parseKey(data);
            if (key)
                this.onGameInput(key);
        }
    }
    parseKey(data) {
        const s = data.toString('utf8');
        // Modifier + arrow keys (resize)
        const modParam = this.modifierKey === 'ctrl' ? '5' : '3';
        if (s === `\x1b[1;${modParam}C`)
            return 'resize-right';
        if (s === `\x1b[1;${modParam}D`)
            return 'resize-left';
        if (s === '\x1b[A')
            return 'up';
        if (s === '\x1b[B')
            return 'down';
        if (s === '\x1b[C')
            return 'right';
        if (s === '\x1b[D')
            return 'left';
        if (s === 'w' || s === 'W')
            return 'up';
        if (s === 'a' || s === 'A')
            return 'left';
        if (s === 's' || s === 'S')
            return 'down';
        if (s === 'd' || s === 'D')
            return 'right';
        if (data.length === 1 && data[0] === 0)
            return 'pause';
        if (s === 'p' || s === 'P')
            return 'pause';
        if (s === 'x' || s === 'X')
            return 'minimize';
        if (s === 'r' || s === 'R')
            return 'reset';
        if (s === 'f' || s === 'F')
            return 'flag';
        if (s === 'h' || s === 'H')
            return 'help';
        if (s === 'm' || s === 'M')
            return 'next-game';
        if (s === ' ')
            return 'space';
        if (s === '\r' || s === '\n')
            return 'enter';
        if (s === '\t')
            return 'tab';
        if (s === '\x1b[Z')
            return 'shift-tab';
        if (data.length === 1 && data[0] === 3)
            return 'ctrl-c';
        if (data.length === 1 && data[0] === 0x1b)
            return 'escape';
        return null;
    }
}
exports.InputRouter = InputRouter;
//# sourceMappingURL=input-router.js.map