"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TmuxControlClient = void 0;
const child_process_1 = require("child_process");
const logger_1 = require("../../lib/logger");
const tmux_control_parser_1 = require("./tmux-control-parser");
const logger = (0, logger_1.createLogger)('tmux-control-client');
const DEFAULT_CONTROL_CLIENT_IDLE_TIMEOUT_MS = 30_000;
/**
 * Thin wrapper around a tmux control mode child process.
 *
 * This class is intentionally small in Phase 2:
 * - It owns the child process lifecycle
 * - It parses stdout into events
 * - It surfaces a minimal input/resize/cleanup interface
 */
class TmuxControlClient {
    parser = new tmux_control_parser_1.TmuxControlParser();
    handlers = new Set();
    spawnProcess;
    tmuxBinary;
    idleTimeoutMs;
    child = null;
    sessionName = null;
    idleTimer = null;
    started = false;
    constructor(options = {}) {
        this.spawnProcess = options.spawnProcess ?? ((command, args, spawnOptions) => (0, child_process_1.spawn)(command, args, spawnOptions));
        this.tmuxBinary = options.tmuxBinary ?? 'tmux';
        this.idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_CONTROL_CLIENT_IDLE_TIMEOUT_MS;
    }
    start(sessionName) {
        if (this.started) {
            return;
        }
        this.sessionName = sessionName;
        this.child = this.spawnProcess(this.tmuxBinary, ['-C', 'attach-session', '-t', sessionName], { stdio: 'pipe' });
        this.started = true;
        this.child.stdout.setEncoding('utf8');
        this.child.stdout.on('data', (chunk) => {
            this.touch();
            const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
            for (const event of this.parser.push(text)) {
                this.emit(event);
            }
        });
        this.child.stderr.setEncoding('utf8');
        this.child.stderr.on('data', (chunk) => {
            const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
            this.emit({ type: 'error', error: new Error(text.trim() || 'tmux control stderr') });
        });
        this.child.on('close', (code) => {
            for (const event of this.parser.flush()) {
                this.emit(event);
            }
            this.emit({ type: 'exit', exitCode: code });
            this.stop();
        });
        this.child.on('error', (error) => {
            this.emit({ type: 'error', error });
            this.stop();
        });
        this.resetIdleTimer();
        logger.debug('start', { sessionName });
    }
    onEvent(handler) {
        this.handlers.add(handler);
        return () => {
            this.handlers.delete(handler);
        };
    }
    sendInput(input) {
        if (!this.child?.stdin.writable) {
            throw new Error('Tmux control client is not writable');
        }
        this.touch();
        this.child.stdin.write(input);
    }
    resize(cols, rows) {
        if (!this.child?.stdin.writable) {
            throw new Error('Tmux control client is not writable');
        }
        this.touch();
        this.child.stdin.write(`refresh-client -C ${cols}x${rows}\n`);
    }
    stop() {
        if (this.idleTimer) {
            clearTimeout(this.idleTimer);
            this.idleTimer = null;
        }
        if (this.child) {
            this.child.removeAllListeners();
            this.child.stdout.removeAllListeners();
            this.child.stderr.removeAllListeners();
            this.child.kill();
            this.child = null;
        }
        this.started = false;
    }
    isStarted() {
        return this.started;
    }
    emit(event) {
        for (const handler of this.handlers) {
            handler(event);
        }
    }
    touch() {
        this.resetIdleTimer();
    }
    resetIdleTimer() {
        if (this.idleTimeoutMs <= 0) {
            return;
        }
        if (this.idleTimer) {
            clearTimeout(this.idleTimer);
        }
        this.idleTimer = setTimeout(() => {
            logger.debug('idle-timeout', { sessionName: this.sessionName });
            this.stop();
        }, this.idleTimeoutMs);
    }
}
exports.TmuxControlClient = TmuxControlClient;
