Source: plugins/inbound/api/base.js

const EventEmitter = require('events');
const Basedata = require('../../../models/basedata');

/**
 * Class for REST API communication
 * @class plugins/inbound/api
 * @namespace plugins/inbound/api
 * @memberof plugins/inbound/api
  */
class restapi extends EventEmitter {

    /**
     * Constructor
     * 
     * Sets up everything, starts service REST API
     */
    constructor() {
        super();
        global.plgManager.logger.info('-------- PLUGIN RESTAPI -----------');
        this.katsysProcess = null;
        this.registerForEvents();
        this.serviceProcId = null;
        this.loadConfig((success) => {
            if (success) {
                // set plugin as configured
                this.initializePlugin((initsuccess) => {
                    global.plgManager.logger.debug('PLUGIN | RESTAPI | initialized Plugin: ' + initsuccess);
                    if (initsuccess) {
                        this.isConfigured = true;
                        this.prepareService();
                        this.wireServiceCommunication();
                        this.configService();
                        this.startService();
                    }
                })
            }
        })
        this.basedata = new Basedata(global.plgManager.logger);
    }

    /**
     * Registration of Events at the plugin manager (hook in to events provided by the plugin manager)
     */
    registerForEvents() {
        global.plgManager.logger.info('PLUGIN | RESTAPI | Registering events');
        global.plgManager.on('event_pluginConfig_refreshed', (namespace) => {
            if (namespace === 'restapi') {
                // plugins config has changed --> refresh
                this.loadConfig((success) => {
                    if (success) {
                        global.plgManager.logger.info('PLUGIN | RESTAPI | successfully reloaded plugin configuration');
                        this.restartService();
                    } else {
                        global.plgManager.logger.error('PLUGIN | RESTAPI | could not reload plugin config!');
                    }
                });
            }
        })
    }

    /**
     * Plugin-specific implementation
     */
    newFeedback(feedbackInfo) {
        global.plgManager.logger.info('PLUGIN | RESTAPI | Recieved new Feedback from REST API');
        global.plgManager.event_new_feedback_received(feedbackInfo.operationUUID, feedbackInfo.basedataUUID, feedbackInfo.stateId);
    }
    




    /**
     * Loads configuration for RESDT API Service
     * @memberof plugins/inbound/katsys
     */
    loadConfig(callback) {
        global.plgManager.loadConfigFromStore('restapi', (configRows) => {
            if (configRows !== null) {
                this.config = configRows[0];
                this.config = JSON.parse(this.config.configstore);
                callback(true);
            } else {
                callback(false);
            }
            global.plgManager.logger.info('PLUGIN | RESTAPI | Configuration loaded from core database');
        })
    }

    /**
     * returns config parameter for given fieldname
     * @param {string} fieldname 
     * @memberof plugins/inbound/api
     */
    getConfigValue(fieldname) {
        var retVal = null;
        this.config.fields.forEach((field) => {
            if (field.fieldname === fieldname) {
                retVal = field.value;
            }
        });
        return retVal;
    }

    /**
     * reconfigures divera plugin with new config settings
     * @param {function} callback success, true or false
     * @memberof plugins/inbound/api
     */
    initializePlugin(callback) {
        // LAU

        this.serviceConfig = {
            httpPort: this.getConfigValue('httpPort'),
            httpsPort: this.getConfigValue('httpsPort'),
            runOnHTTPS: this.getConfigValue('runOnHTTPS'),
            runOnHTTP: this.getConfigValue('runOnHTTP'),
            loglevel: 'debug'
        }

        if ((typeof this.serviceConfig.httpPort !== 'undefined') && (typeof this.serviceConfig.runOnHTTP !== 'undefined') || (typeof this.serviceConfig.httpsPort !== 'undefined') && (typeof this.serviceConfig.runOnHTTPS !== 'undefined')) {
            global.plgManager.logger.info('PLUGIN | RESTAPI | Properly inititlized settings');
            callback(true);
        } else {
            global.plgManager.logger.error('PLUGIN | RESTAPI | could not initialize settings');
            callback(false);
        }
    }

    /**
     * Wires messages from service to event model of plugin
     * All Messages in service need to be wired here to be recognised in plugin
     * @memberof plugins/inbound/api
     */
    wireServiceCommunication() {
        this.serviceProcess.on('message', function (msg) {
            var payload = [];
            try {
                payload = JSON.parse(msg);
            } catch (err) {
                payload = [];
            }
            if (typeof payload.logmessage != 'undefined') {
                msg = payload.logmessage;
            }
            console.log('PLUGIN | RESTAPI | SERVICE | ' + msg);
            var payload = null;
            try {
                payload = JSON.parse(msg);
            } catch (err) {
                payload = err.message;
            }
            if (typeof payload.feedbackState != 'undefined') {
                var basedataUUID = payload.feedbackState.basedataUUID;
                var operationUUID = payload.feedbackState.operationUUID;
                var feedbackState = payload.feedbackState.feedbackState;
                global.plgManager.event_new_feedback_received(operationUUID, basedataUUID, feedbackState);
                global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | Sending new Feedback to PluginManager');
            } else if (typeof payload.newDeviceRegistered != 'undefined') {

                var basedataId = payload.newDeviceRegistered.basedataId;
                var deviceName = payload.newDeviceRegistered.deviceName;
                var deviceModel = payload.newDeviceRegistered.deviceModel;
                var devicePlatform = payload.newDeviceRegistered.devicePlatform;
                var deviceOsVersion = payload.newDeviceRegistered.deviceOsVersion;
                var deviceUUID = payload.newDeviceRegistered.deviceUUID;

                this.basedata.getBaseDataForId(basedataId, (basedataRows) => {
                    if (basedataRows != null){
                        basedataRows.forEach((entry)=> {
        
                            var message = "Es wurde ein neues Gerät \'"+ deviceName +"\' ("+devicePlatform+") von " + entry.lastname + " " + entry.firstname + " hinzugefügt";

                            global.plgManager.event_new_admin_notification(message);
                            global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | Sending admin notification for new device to PluginManager');
                       })
                   }
               });     
            
            } else if (typeof payload.logmessage != 'undefined') {
                global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | ' + payload.logmessage);
            } else if (typeof payload.error != 'undefined') {
                // child has sent an error
                // try restarting the whole service
                global.plgManager.event_new_admin_notification('RESTAPI Service meldet einen Fehler');
                this.restartService();
            }
            if (typeof payload.logmessage != 'undefined') {
                global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | ' + payload.logmessage);
            } else if (typeof payload.event != 'undefined') {
                // service send structured data
                
                if (payload.event.event === 'event_new_feedback') {
                    var message = payload.event.feedback;
                    console.log('PLUGIN | RESTAPI | SERVICE | NEW FEEDBACK');
                    global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | NEW FEEDBACK');
                    //this.event_new_feedback_received()
                } else if (payload.event.event === 'error') {
                    console.log('PLUGIN | RESTAPI | SERVICE | ERROR');
                    global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | ERROR ' + JSON.stringify(payload.event.error));
                    global.plgManager.event_new_admin_notification('REST API Fehler: ' + JSON.stringify(payload.event.error));
                    this.restartService();
                }
            } else {
                global.plgManager.logger.info('PLUGIN | RESTAPI | SERVICE | UNSOLICITED MESSAGE: ' + msg);
            }
        }.bind(this));
    }

    

    /**
     * Creates the service as a seperate node-process (fork)
     * sets the serviceProcId of the forked process
     * @memberof plugins/inbound/api
     */
    prepareService() {
        global.plgManager.logger.info('PLUGIN | RESTAPI | Starting Service');
        const { fork } = require('child_process');
        this.serviceProcess = fork(__dirname + '/app.js');
        this.serviceProcId = this.serviceProcess.pid;
        this.serviceProcess.title = 'ALARMiator Plugin - REST API';
        global.plgManager.logger.info('PLUGIN | RESTAPI | Service started with pid ' + this.serviceProcId);
        this.serviceProcess.on('exit', function (code) {
            this.serviceProcess = null;
            console.log("RESTAPI Service EXITED " + code);
        });
    }

   
    /**
     * Sends the service configuration to the process
     */
    configService() {
        this.serviceProcess.send({ config: this.serviceConfig });
    }

    /**
     * tells the service to connect
     */
    startService() {
        this.serviceProcess.send({ start: 1 });
    }

    /**
     * restarts the Service
     */
    restartService() {
        global.plgManager.logger.info('PLUGIN | RESTAPI | restart Service...');
        if (this.serviceProcess !== null) {
            global.plgManager.logger.info('PLUGIN | RESTAPI | Killing Service...');
            this.serviceProcess.kill("SIGHUP");
        }
        this.initializePlugin((initsuccess) => {
            global.plgManager.logger.debug('PLUGIN | RESTAPI | initialized Plugin: ' + initsuccess);
            if (initsuccess) {
                this.isConfigured = true;
                this.prepareService();
                this.wireServiceCommunication();
                this.configService();
                this.startService();
            }
        })
    }
}

module.exports = restapi;