"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.PtyManager = void 0;
const pty = __importStar(require("node-pty"));
const child_process_1 = require("child_process");
class PtyManager {
    onData;
    onExit;
    ptyProcess = null;
    constructor(onData, onExit) {
        this.onData = onData;
        this.onExit = onExit;
    }
    resolveCommand(command) {
        if (process.platform !== 'win32')
            return command;
        if (/\.\w+$/.test(command) || command.includes('\\') || command.includes('/')) {
            return command;
        }
        try {
            const result = (0, child_process_1.execFileSync)('where.exe', [command], { encoding: 'utf-8', timeout: 5000 });
            const paths = result.trim().split(/\r?\n/).map(p => p.trim()).filter(Boolean);
            return paths.find(p => /\.exe$/i.test(p))
                || paths.find(p => /\.(cmd|bat)$/i.test(p))
                || paths[0];
        }
        catch {
            throw new Error(`command not found: ${command}`);
        }
    }
    spawn(command, args, cols, rows) {
        let resolved = this.resolveCommand(command);
        let spawnArgs = args;
        if (process.platform === 'win32' && /\.(cmd|bat)$/i.test(resolved)) {
            spawnArgs = ['/c', resolved, ...args];
            resolved = 'cmd.exe';
        }
        this.ptyProcess = pty.spawn(resolved, spawnArgs, {
            name: 'xterm-256color',
            cols,
            rows,
            cwd: process.cwd(),
            env: (() => {
                const env = {};
                for (const [k, v] of Object.entries(process.env)) {
                    if (v !== undefined)
                        env[k] = v;
                }
                env.SPLITGAME_ACTIVE = '1';
                return env;
            })(),
            ...(process.platform === 'win32' ? { useConpty: true } : {}),
        });
        this.ptyProcess.onData(this.onData);
        this.ptyProcess.onExit(({ exitCode }) => this.onExit(exitCode ?? 1));
    }
    write(data) {
        // ConPTY double-translation fix: outer terminal uses VT convention (0x7F=Backspace,
        // 0x08=Ctrl+Backspace) but inner ConPTY uses Win32 convention (0x08=Backspace,
        // 0x7F=Ctrl+Backspace). Swap so the child shell sees the correct key events.
        if (process.platform === 'win32' && (data.includes('\x7f') || data.includes('\x08'))) {
            let fixed = '';
            for (let i = 0; i < data.length; i++) {
                const c = data.charCodeAt(i);
                fixed += c === 0x7f ? '\x08' : c === 0x08 ? '\x7f' : data[i];
            }
            this.ptyProcess?.write(fixed);
            return;
        }
        this.ptyProcess?.write(data);
    }
    resize(cols, rows) {
        try {
            this.ptyProcess?.resize(Math.max(1, cols), Math.max(1, rows));
        }
        catch {
            // Process may have already exited
        }
    }
    kill() {
        try {
            this.ptyProcess?.kill();
        }
        catch {
            // Already dead
        }
    }
    get pid() {
        return this.ptyProcess?.pid;
    }
}
exports.PtyManager = PtyManager;
//# sourceMappingURL=pty-manager.js.map