(function () {
    var MODULE_NAME = "simulatePLC",
        ENABLE_LOGGING = true,
        RECORD_LOG = false,
        logger = shmi.requires("visuals.tools.logging").createLogger(MODULE_NAME, ENABLE_LOGGING, RECORD_LOG),
        fLog = logger.fLog,
        log = logger.log,
        module = shmi.pkg(MODULE_NAME);

    // MODULE CODE - START

    /* private variables */
    const CYCLE_TIME = 20
    const MAX_CURVES = 5
    const MAX_X = 4
    const ITEM_MSG = "stOsziSim.sMsg"
    const ITEM_SETUP = "stOsziSim.sSetup"
    const ITEM_X = "stOsziSim.sX"
    const FS = ","

    let iCycleMax = 0
    let iDelay = 0
    let iStep = 0
    let iX = 0
    let rY = 0.0
    let rYStart = 0.0
    let sX = ""
    let sY = []
    let sOsziSetup = ""

    /**
    * set webIQ item
    * @param {string} sItem item name
    * @param {number} oValue value to set (int,float,string,bool)
    */
    function setItem(sItem, oValue) {
        const im = shmi.requires("visuals.session.ItemManager")
        if (im.items[sItem]) { // item subscribed => write value
            im.writeValue(sItem, oValue)
            log(`writeValue(${sItem}, ${oValue})`)
            return true
        } else {
            // item not subscribed => use writeDirect with callback
            let jItem = {}
            jItem[sItem] = oValue
            return new Promise((resolve, reject) => {
                im.writeDirect(jItem, function (s, i) {
                    if (s.errc) {
                        shmi.notify(`Invalid item name "${sItem}"`)
                        reject(false)
                    } else {
                        log(`writeDirect(${sItem}, ${oValue})`)
                        resolve(true)
                    }
                });
            })
        }
    }
    /* private functions */
    function simulateTrend() {
        let y = 0
        let rOffset = 0.5
        let iPlcCycleTime = 4
        if (iStep === 10) {
            iDelay++
            if (iDelay > 30) {
                iCycleMax = 80
                iX = 0
                rY = rYStart
                rYStart += 0.1
                sX = '['
                for (let i = 0; i < MAX_CURVES; i++) {
                    sY[i] = '['
                }
                sX += iX
                sOsziSetup = `{
                            "config": {
                              "responsive": true,
                              "doubleClickDelay": 400,
                              "displayModeBar": true,
                              "displaylogo": false,
                              "modeBarButtonsToRemove": ["toImage", "lasso2d", "zoom2d", "select2d", "autoScale2d"],
                              "modebar_bgcolor" : "yellow",
                              "modebar_color" : "red"
                            },
                            
                            "layout": {
                              "title": "\${title.chart}",
                              "xaxis": {
                                "title": "x axis"
                              },
                              "yaxis": {
                                "title": "y0 axis"
                              },
                              "yaxis2": {
                                "title": "y1 axis",
                                "overlaying": "y",
                                "side": "right"
                              },
                                "showlegend": true,
                                "legend": {"x": 1, "y": 0.02}
                            },
                            
                            "data": [
                               {
                                "name": "y0 data",
                                "type": "scatter"
                               },
                               {
                                "name": "y1 data",
                                "_yaxis": "y2",
                                "type": "scatter"
                               }
                               ]
                        }`


                for (let i = 0; i < MAX_CURVES; i++) {
                    y = Math.sin(rY) + i * 0.1
                    sY[i] +=  (y + 0).toFixed(3)
                }

                setItem(ITEM_SETUP, sOsziSetup)
                log(sOsziSetup)
                iStep++
            }
        } else if (iStep === 11) {
            iX++
            rY += 0.1
            sX += FS + (iX * iPlcCycleTime).toFixed(0)

            for (let i = 0; i < MAX_CURVES; i++) {
                y = Math.sin(rY) + i * 0.1
                sY[i] += FS + (y + 0).toFixed(3)
            }
            // y = Math.sin(rY + 0.5) * 2
            // sY[1] += FS + (y + rOffset).toFixed(3)

            sOsziMsg = 'state ' + (100 * iX / iCycleMax).toFixed(0)
            setItem(ITEM_MSG, sOsziMsg)
            if (iX >= iCycleMax) {
                sX += "]"
                setItem(ITEM_X, sX)
                log("X=" + sX)

                for (let i = 0; i < MAX_CURVES; i++) {
                    sY[i] += "]"
                    setItem(`stOsziSim.sY[${i}]`, sY[i])
                    log(`Y${i}=\n` + sY[i])
                }

                iStep = 100;
            }
        } else if (iStep === 100) {
            sOsziMsg = 'state done'
            setItem(ITEM_MSG, sOsziMsg)
            log(sOsziMsg)
            iDelay = 0
            iStep++
        } else if (iStep === 101) {
            iDelay++
            if (iDelay > 60) {
                setItem(ITEM_MSG, '')
                iStep = 200
            }
        }

        if (iStep < 200) {
            setTimeout(simulateTrend, CYCLE_TIME);
        }
    }
    /**
     * Implements local-script run function.
     *
     * This function will be called each time a local-script will be enabled.
     *
     * @param {LocalScript} self instance reference of local-script control
     */
    module.run = function (self) {
        const im = shmi.requires("visuals.session.ItemManager");
        let tok = im.subscribe([ITEM_MSG], (name, value, type) => {
            const arW = value.split(" ")
            if (arW[0] === "cmd") {
                if (arW[1] === "rec-0") {
                    iDelay = 0
                    iStep = 10
                    setItem(ITEM_MSG, "state wait")
                    setTimeout(simulateTrend, CYCLE_TIME)
                } else {
                    setItem(ITEM_MSG, "")
                }
            }

        });
        /* called when this local-script is disabled */
        self.onDisable = function () {
            tok.unlisten()
            self.run = false; /* from original .onDisable function of LocalScript control */
        };
    };

    // MODULE CODE - END
    fLog("module loaded");
})();
