"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProcessManager = void 0;
const child_process_1 = require("child_process");
const communication_config_1 = require("./communication-config");
const step_handler_rpc_processor_1 = require("../step-handler-rpc-processor");
const step_handler_rpc_stdin_processor_1 = require("../step-handler-rpc-stdin-processor");
class ProcessManager {
    constructor(options) {
        this.options = options;
    }
    async spawn() {
        const { command, args, logger, context = 'Process' } = this.options;
        // Get communication configuration
        const commConfig = (0, communication_config_1.createCommunicationConfig)(command);
        this.communicationType = commConfig.type;
        logger.debug(`[${context}] Spawning process`, {
            command,
            args,
            communicationType: this.communicationType
        });
        // Spawn the process
        this.child = (0, child_process_1.spawn)(command, args, commConfig.spawnOptions);
        // Create appropriate processor based on communication type
        this.processor = this.communicationType === 'rpc'
            ? new step_handler_rpc_stdin_processor_1.RpcStdinProcessor(this.child)
            : new step_handler_rpc_processor_1.RpcProcessor(this.child);
        // Initialize the processor
        await this.processor.init();
        return this.child;
    }
    handler(method, handler) {
        if (!this.processor) {
            throw new Error('Process not spawned yet. Call spawn() first.');
        }
        this.processor.handler(method, handler);
    }
    onMessage(callback) {
        if (!this.processor) {
            throw new Error('Process not spawned yet. Call spawn() first.');
        }
        this.processor.onMessage(callback);
    }
    onProcessClose(callback) {
        if (!this.child) {
            throw new Error('Process not spawned yet. Call spawn() first.');
        }
        this.child.on('close', callback);
    }
    onProcessError(callback) {
        if (!this.child) {
            throw new Error('Process not spawned yet. Call spawn() first.');
        }
        this.child.on('error', callback);
    }
    onStderr(callback) {
        if (!this.child) {
            throw new Error('Process not spawned yet. Call spawn() first.');
        }
        this.child.stderr?.on('data', callback);
    }
    onStdout(callback) {
        if (!this.child) {
            throw new Error('Process not spawned yet. Call spawn() first.');
        }
        // Only for non-RPC mode (in RPC mode, stdout is used for communication)
        if (this.communicationType !== 'rpc') {
            this.child.stdout?.on('data', callback);
        }
    }
    kill() {
        if (this.child) {
            this.child.kill();
        }
    }
    close() {
        if (this.processor) {
            this.processor.close();
        }
        this.processor = undefined;
        this.child = undefined;
    }
    get process() {
        return this.child;
    }
    get commType() {
        return this.communicationType;
    }
}
exports.ProcessManager = ProcessManager;
