'use strict';  // all variables must be defined

let myWsServer = null; // web server object
let sTarget = ""; // target project name
let iID = 0; // id for API cmd's
let jSend = {};

/**
 * establish connection to WebIQ server
 * 
 * @param {string} sServer (e.g. "ws://127.0.0.1:10123/";)
 * @param {string} sProtocol (e.g. "smarthmi-connect";)
 */
function wsConnect(sServer, sProtocol) {
  return new Promise(function (resolve, reject) {
    let bTimeOutActive = false
    let oTimeOutFunc = null
    if (sProtocol !== "") {
      try {
        bTimeOutActive = true
        oTimeOutFunc = setTimeout(function () {
          myWsServer = null
          console.error("setTimeout called")
          bTimeOutActive = false
          reject()
        }, 2000)
        myWsServer = new WebSocket(sServer, sProtocol)
      }
      catch (err) {
        msgBox("error", eval(l.connectFailed));
        reject(err);
      }
    } else {
      myWsServer = new WebSocket(sServer);
    }

    myWsServer.onopen = function (event) {
      if (SHOW_WS_TELEGRAMS) {
        console.warn(`>CB:Connected to ${sServer} OK`)
      }
      clearTimeout(oTimeOutFunc)
      resolve("connection OK");
    };
    myWsServer.onerror = function (err) {
      if (bTimeOutActive) {
        clearTimeout(oTimeOutFunc)
        myWsServer = null
        console.error("onError called")
        msgBox("error", eval(l.connectFailed))
        reject(err)
      }
    }
  });
}
/**
 * close connection to WebIQ server
 * 
 */
function wsClose() {
  return new Promise(function (resolve, reject) {
    if (SHOW_WS_TELEGRAMS)
      console.warn(`>Close connection requested`);
    myWsServer.close()
    myWsServer.onclose = function (event) {
      myWsServer = null
      if (SHOW_WS_TELEGRAMS)
        console.warn(`>>>CB:onClose connection OK`)
      resolve(event)
    };

    myWsServer.onerror = function (err) {
      // msgBox("error", `Close connection to ${sWebIQServer} failed`);
      reject(err);
    };
  });
}
/**
 * send message to WebIQ server and waits for response
 * @param {json} jCmd 
 * @param {boolean} bThrowError true=throw error when response.errc>0
 * @return {json} received command response
 */
function wsSendRecv(jCmd, bThrowErr) {
  if (bThrowErr === undefined)
    bThrowErr = true
  if (myWsServer === null) {
    abortJS(eval(l.connectFailed),true)
  }
  return new Promise(function (resolve, reject) {
    // add target project name if defined => to select the defined project

    jCmd.id = ++iID;
    if (sTarget !== "") {
      jCmd.target = sTarget;
    }
    jSend = jCmd;
    let sCmd = JSON.stringify(jCmd, null, 0);
    myWsServer.send(sCmd);
    if (SHOW_WS_TELEGRAMS)
      console.warn("S:" + JSON.stringify(jCmd, null, 2));

    myWsServer.onerror = function (err) {
      msgBox("error", `Receive error ${err.message}`);
      reject(err);
    };
    myWsServer.onmessage = function (evt) {
      let jResp = JSON.parse(evt.data);
      if (jResp.cmd === "connect.event") {
        jResp;
      } else {
        if (SHOW_WS_TELEGRAMS)
          console.warn("R:" + JSON.stringify(jResp, null, 2));
        if (iID !== jResp.id) {
          jResp.error = {};
          jResp.error.errc = 99999;  // programming error?
          jResp.error.message = `${jResp.cmd} failed. Code=${jResp.error.errc} msg=Invalid id.\nSend=${iID} ${jSend.cmd}\nRecv=${jResp.id} ${jResp.cmd}`;
          //alert(oResp.error.message);
          reject(jResp);
        } else if (isRespOK(jResp)) {
          resolve(jResp);
        } else {
          if (bThrowErr === true) {
            jResp.error.message = `${jResp.cmd} failed. code=${jResp.error.errc} msg=${jResp.error.message}`;
            reject(jResp);
          } else {
            resolve(jResp);
          }
        }
      }
    }
  });
}

/**
 * Waits for API response. Some commands returns multiple messages.
 * Func. is necessary, because wsSendRecv only waits for 1 response msessage 
 * @param {json} jResp1 first response, for checking of ID & commands
 * @param {boolean} bThrowError true=throw error when response.errc>0
 * @return {json} received command response
 */
function wsRecv(jResp1, bThrowErr) {
  if (myWsServer === null) {
    abortJS(eval(l.connectFailed))
  }
  return new Promise(function (resolve, reject) {
    let toRecv = setTimeout(() => {
      abortJS(`Nothing received within timeout.\nid=${jResp1.id} cmd=${jResp1.cmd}`)
    }, iTimeOut)

    myWsServer.onerror = function (err) {
      msgBox("error", `Receive error ${err.message}`);
      reject(err);
    };
    myWsServer.onmessage = function (evt) {
      clearTimeout(toRecv)
      let jResp = JSON.parse(evt.data);
      if (SHOW_WS_TELEGRAMS)
        console.log("R: " + jResp.id + ":" + jResp.cmd);
      if (jResp1.id !== jResp.id) {
        jResp.error = {};
        jResp.error.errc = 99999;  // programming error?
        jResp.error.message = `${jResp.cmd} failed. Code=${jResp.error.errc} msg=Invalid id.\nSend=${iID} ${jSend.cmd}\nRecv=${jResp.id} ${jResp.cmd}`;
        //alert(oResp.error.message);
        reject(jResp);
      } else if (isRespOK(jResp)) {
        resolve(jResp);
      } else {
        if (bThrowErr === true) {
          jResp.error.message = `${jResp.cmd} failed. code=${jResp.error.errc} msg=${jResp.error.message}`;
          reject(jResp);
        } else {
          resolve(jResp);
        }
      }
    }
  });
}
/**
 * Check if response  reports an error
 */
function isRespOK(oResp) {
  return (oResp.error === null);
}


