/**
 * MK1 Kernel - Owns everything
 *
 * Responsibilities:
 * - Create screen with stable options
 * - Attach resize controller
 * - Attach exit handlers
 * - Enforce singleton (destroy old screen before creating new)
 */
import blessed from 'neo-blessed';
import { enableStdoutGuard, disableStdoutGuard } from './stdoutGuard.js';
import { registerScreen, unregisterScreen, restoreTerminal } from './terminalRestore.js';
import { initResizeController, destroyResizeController, forceRebuild } from './resizeController.js';
import { logger } from './logger.js';
import { fileLogger, setBlessedActive } from './log.js';
export class MK1Kernel {
    screen = null;
    onRebuild = null;
    /**
     * Start kernel
     */
    async start(renderFn, options = {}) {
        // Enforce singleton: destroy old screen if exists
        if (globalThis.__MK1_SCREEN__) {
            logger.warn('Old MK1 screen detected, destroying...');
            try {
                globalThis.__MK1_SCREEN__.destroy();
            }
            catch {
                // Ignore
            }
            globalThis.__MK1_SCREEN__ = undefined;
        }
        // Enable stdout guard BEFORE creating screen
        enableStdoutGuard();
        // Ensure stdin is a TTY and can be put in raw mode
        if (!process.stdin.isTTY) {
            throw new Error('stdin is not a TTY. Cannot start TUI.');
        }
        // Explicitly resume stdin to ensure it stays open (keeps process alive)
        process.stdin.resume();
        process.stdin.setEncoding('utf8');
        // Create screen with stable options
        this.screen = blessed.screen({
            smartCSR: true,
            fullUnicode: true,
            warnings: false,
            title: '4Runr MK1',
            output: process.stdout,
            input: process.stdin,
            scrollable: false, // Disable screen-level scrolling
            alwaysScroll: false,
            fastCSR: true, // Faster rendering
            useBCE: true, // Background color erase
            terminal: process.env.TERM || 'xterm-256color',
        });
        // Ensure screen is ready and terminal is in raw mode
        if (this.screen.program) {
            // Clear screen initially
            this.screen.program.clear();
            // Ensure raw mode is enabled
            if (this.screen.program.setRawMode) {
                this.screen.program.setRawMode(true);
            }
        }
        // Keep stdin open to prevent process from exiting
        // This is critical - without this, the process may exit immediately
        process.stdin.on('error', (error) => {
            logger.error(`stdin error: ${error.message}`);
        });
        // Prevent stdin from closing
        process.stdin.on('end', () => {
            logger.warn('stdin ended - this should not happen in TUI mode');
        });
        // Register singleton
        globalThis.__MK1_SCREEN__ = this.screen;
        // Register for terminal restore
        registerScreen(this.screen);
        // CRITICAL: Mark blessed as active - from now on, all logs go to file only
        setBlessedActive(true);
        fileLogger.force('[KERNEL] Blessed screen created - switching to file-only logging');
        fileLogger.force(`[KERNEL] Log file: ${fileLogger.getLogPath()}`);
        fileLogger.force(`[KERNEL] Screen size: ${this.screen.width}x${this.screen.height}`);
        // Add screen destroy handler to debug why it might be destroyed
        this.screen.on('destroy', () => {
            fileLogger.warn('Screen was destroyed - this should not happen during normal operation');
        });
        // Store rebuild callback
        this.onRebuild = options.onRebuild || null;
        // Initialize resize controller
        if (this.onRebuild) {
            initResizeController(this.screen, this.onRebuild);
        }
        // Clear screen and prepare for rendering
        if (this.screen.program) {
            this.screen.program.clear();
            this.screen.program.hideCursor();
        }
        // Initial render
        fileLogger.force('[KERNEL] STEP 1: About to call renderFn() callback');
        fileLogger.force(`[KERNEL] STEP 1.5: renderFn type: ${typeof renderFn}`);
        fileLogger.force(`[KERNEL] STEP 1.6: screen.children BEFORE renderFn: ${this.screen.children?.length || 0}`);
        let renderFnCompleted = false;
        let renderFnError = null;
        try {
            fileLogger.force('[KERNEL] STEP 2: Calling renderFn() NOW...');
            renderFn();
            renderFnCompleted = true;
            fileLogger.force('[KERNEL] STEP 3: renderFn() returned (no exception)');
        }
        catch (error) {
            renderFnError = error;
            const errorMsg = error instanceof Error ? error.message : String(error);
            fileLogger.force(`[KERNEL] STEP 3 ERROR: renderFn() threw error: ${errorMsg}`);
            if (error instanceof Error && error.stack) {
                fileLogger.force(`[KERNEL] STEP 3 ERROR STACK: ${error.stack}`);
            }
            // Don't throw - continue to see what happens
        }
        fileLogger.force(`[KERNEL] STEP 4: renderFn completed=${renderFnCompleted} error=${renderFnError ? 'yes' : 'no'}`);
        fileLogger.force(`[KERNEL] STEP 4.5: screen.children AFTER renderFn: ${this.screen.children?.length || 0}`);
        fileLogger.force('[KERNEL] STEP 5: About to call screen.render()');
        this.screen.render();
        fileLogger.force('[KERNEL] STEP 6: screen.render() completed');
        fileLogger.force(`[KERNEL] STEP 6.5: screen.children AFTER screen.render(): ${this.screen.children?.length || 0}`);
        // Force flush to ensure screen is visible
        if (this.screen.program?.flush) {
            this.screen.program.flush();
        }
        // CRITICAL: Focus the screen to ensure it captures input
        // This must be done after render
        if (this.screen.focus) {
            this.screen.focus();
            logger.debug('Screen focused to capture input');
        }
        // CRITICAL: Ensure blessed is actively listening to stdin
        // Blessed needs to have an active listener on stdin to keep the process alive
        // We ensure this by setting up a dummy listener if needed
        if (!process.stdin.listenerCount('data') && !process.stdin.listenerCount('readable')) {
            // Blessed should have set this up, but we ensure it exists
            logger.debug('Ensuring stdin has active listeners');
        }
        // CRITICAL: Keep stdin in flowing mode (not paused)
        // This is essential - if stdin is paused, the process will exit
        if (process.stdin.isPaused()) {
            logger.warn('stdin was paused - resuming to keep process alive');
            process.stdin.resume();
        }
        // Ensure stdin is readable and will keep process alive
        if (!process.stdin.readable) {
            logger.error('stdin is not readable - this will cause the process to exit!');
            process.stdin.resume();
        }
        // Log screen state for debugging (use file logger since blessed is active now)
        fileLogger.info(`MK1 Kernel started (screen: ${this.screen.width}x${this.screen.height})`);
        fileLogger.debug(`Screen has ${this.screen.children?.length || 0} children after render`);
        fileLogger.debug(`stdin readable: ${process.stdin.readable}, paused: ${process.stdin.isPaused()}`);
        // Verify screen is still alive after a brief delay
        setImmediate(() => {
            if (!this.screen) {
                logger.error('Screen was destroyed immediately after creation!');
            }
            else {
                logger.debug('Screen is still alive after initialization');
            }
        });
    }
    /**
     * Rebuild (destroy + recreate)
     */
    async rebuild(reason) {
        logger.debug(`Rebuild requested: ${reason}`);
        if (this.screen && this.onRebuild) {
            const cols = this.screen.width;
            const rows = this.screen.height;
            await this.onRebuild(cols, rows);
        }
    }
    /**
     * Force rebuild (for dbg:panic)
     */
    async panic() {
        logger.warn('PANIC: Force rebuild');
        await forceRebuild();
    }
    /**
     * Get screen instance
     */
    getScreen() {
        return this.screen;
    }
    /**
     * Stop kernel
     */
    stop() {
        logger.info('Stopping MK1 Kernel');
        // Destroy resize controller
        destroyResizeController();
        // Unregister screen
        unregisterScreen();
        // Disable stdout guard
        disableStdoutGuard();
        // Destroy screen
        if (this.screen) {
            try {
                this.screen.destroy();
            }
            catch {
                // Ignore
            }
            this.screen = null;
        }
        // Clear singleton
        globalThis.__MK1_SCREEN__ = undefined;
        // Restore terminal
        restoreTerminal();
        logger.info('MK1 Kernel stopped');
    }
}
//# sourceMappingURL=kernel.js.map