const { Reactor_CSTR, Reactor_PFR } = require('./specificClass.js');


class nodeClass {
    /**
    * Node-RED node class for advanced-reactor.
    * @param {object} uiConfig - Node-RED node configuration
    * @param {object} RED - Node-RED runtime API
    * @param {object} nodeInstance - Node-RED node instance
    * @param {string} nameOfNode - Name of the node
    */
    constructor(uiConfig, RED, nodeInstance, nameOfNode) {
        // Preserve RED reference for HTTP endpoints if needed
        this.node = nodeInstance;
        this.RED = RED;
        this.name = nameOfNode;
        this.source = null;

        this._loadConfig(uiConfig)
        this._setupClass();

        this._attachInputHandler();
        this._registerChild();
        this._startTickLoop();
        this._attachCloseHandler();
    }

    /**
     * Handle node-red input messages
     */
    _attachInputHandler() {
        this.node.on('input', (msg, send, done) => {

            switch (msg.topic) {
                case "clock":
                    this.source.updateState(msg.timestamp);
                    send([msg, null, null]);
                    break;
                case "Fluent":
                    this.source.setInfluent = msg;
                    break;
                case "OTR":
                    this.source.setOTR = msg;
                    break;
                case "Temperature":
                    this.source.setTemperature = msg;
                    break;
                case "Dispersion":
                    this.source.setDispersion = msg;
                    break;
                case 'registerChild':
                    // Register this node as a parent of the child node
                    const childId = msg.payload;
                    const childObj = this.RED.nodes.getNode(childId); 
                    this.source.childRegistrationUtils.registerChild(childObj.source, msg.positionVsParent);
                    break;
                default:
                    console.log("Unknown topic: " + msg.topic);
            }

            if (done) {
                done();
            }
        });
    }

    /**
     * Parse node configuration
     * @param {object} uiConfig Config set in UI in node-red
     */
    _loadConfig(uiConfig) {
        this.config = {
            general: {
                name: uiConfig.name || this.name,
                id: this.node.id,
                unit: null,
                logging: {
                    enabled: uiConfig.enableLog,
                    logLevel: uiConfig.logLevel
                }
            },
            functionality: {
                positionVsParent: uiConfig.positionVsParent || 'atEquipment', // Default to 'atEquipment' if not specified
                softwareType: "reactor" // should be set in config manager
            },
            reactor_type: uiConfig.reactor_type,
            volume: parseFloat(uiConfig.volume),
            length: parseFloat(uiConfig.length),
            resolution_L: parseInt(uiConfig.resolution_L),
            alpha: parseFloat(uiConfig.alpha),
            n_inlets: parseInt(uiConfig.n_inlets),
            kla: parseFloat(uiConfig.kla),
            initialState: [
                parseFloat(uiConfig.S_O_init),
                parseFloat(uiConfig.S_I_init),
                parseFloat(uiConfig.S_S_init),
                parseFloat(uiConfig.S_NH_init),
                parseFloat(uiConfig.S_N2_init),
                parseFloat(uiConfig.S_NO_init),
                parseFloat(uiConfig.S_HCO_init),
                parseFloat(uiConfig.X_I_init),
                parseFloat(uiConfig.X_S_init),
                parseFloat(uiConfig.X_H_init),
                parseFloat(uiConfig.X_STO_init),
                parseFloat(uiConfig.X_A_init),
                parseFloat(uiConfig.X_TS_init)
            ],
            timeStep: parseFloat(uiConfig.timeStep)
        }
    }

    /**
     * Register this node as a child upstream and downstream.
     * Delayed to avoid Node-RED startup race conditions.
     */
    _registerChild() {
        setTimeout(() => {
        this.node.send([
            null,
            null,
            { topic: 'registerChild', payload: this.node.id, positionVsParent: this.config?.functionality?.positionVsParent || 'atEquipment' }
        ]);
        }, 100);
    }

    /**
     * Setup reactor class based on config
     */
    _setupClass() {
        let new_reactor;

        switch (this.config.reactor_type) {
            case "CSTR":
                new_reactor = new Reactor_CSTR(this.config);
                break;
            case "PFR":
                new_reactor = new Reactor_PFR(this.config);
                break;
            default:
                console.warn("Unknown reactor type: " + uiConfig.reactor_type);
        }

        this.source = new_reactor; // protect from reassignment
        this.node.source = this.source;
    }

    _startTickLoop() {
        setTimeout(() => {
            this._tickInterval = setInterval(() => this._tick(), 1000);
        }, 1000);
    }

    _tick(){
        this.node.send([this.source.getEffluent, null, null]);
    }

    _attachCloseHandler() {
        this.node.on('close', (done) => {
            clearInterval(this._tickInterval);
            done();
        });
    }
}

module.exports = nodeClass;