const { parentPort } = require("worker_threads");
const axios = require("axios");
const fs = require("fs");
const FormData = require("form-data");
const http = require("http");

const Results = {
  Success: "Success",
  Error: "Error",
};

const checkUpdateInfo = async function (DeviceData) {
  return await new Promise((resolve, reject) => {
    //socket_io.emit('Logcat', 'Check upgrade package info')
    // parentPort.postMessage({ event: 'Logcat_info', data: 'Check upgrade package info' })
    parentPort.postMessage({ event: "Logcat_info_t", data: { t: "tip.CUPI" } });
    let fileInfo = DeviceData.fileInfo;
    let device = DeviceData.device;
    if (device.ip === "10.0.0.254") {
      // parentPort.postMessage({ event: 'Logcat_error', data: 'Devices : ' + device.MAC + ',IP : ' + device.ip + ' Unregistered devices do not support upgrades at this time' })
      parentPort.postMessage({
        event: "Logcat_error_t",
        data: { mac: device.MAC, ip: device.ip, t: "tip.UDDNS" },
      });
      reject("Unregistered devices do not support upgrades at this time");
    }
    axios
      .post(
        "http://" + device.ip + "/web.fcgi",
        "function=ToolCheckUpdateInfo" +
          "&updateInfo=" +
          JSON.stringify(fileInfo.ini) +
          "&token=" +
          device.token
      )
      .then((res) => {
        if (res.data.res === 1 && res.data.des === 0) {
          // parentPort.postMessage({ event: 'Logcat_success', data: 'Devices : ' + device.MAC + ',IP : ' + device.ip + ' Check upgrade package info success' })
          parentPort.postMessage({
            event: "Logcat_success_t",
            data: { mac: device.MAC, ip: device.ip, t: "tip.CUPIS" },
          });
          resolve();
        } else {
          // parentPort.postMessage({ event: 'Logcat_error', data: 'Devices : ' + device.MAC + ',IP : ' + device.ip + ' Check upgrade package info error' })
          parentPort.postMessage({
            event: "Logcat_error_t",
            data: { mac: device.MAC, ip: device.ip, t: "tip.CUPIE" },
          });
          reject();
        }
      })
      .catch((res) => {
        parentPort.postMessage({
          event: "console",
          data: "uploadUpdateFile catch res :  " + res.message,
        });
        // parentPort.postMessage({ event: 'Logcat_error', data: 'Devices : ' + device.MAC + ',IP : ' + device.ip + ' Check upgrade package info error' })
        parentPort.postMessage({
          event: "Logcat_error_t",
          data: { mac: device.MAC, ip: device.ip, t: "tip.CUPIE" },
        });
        reject();
      });
  });
};

const uploadUpdateFile = async function (DeviceData) {
  return await new Promise(async (resolve, reject) => {
    let fileInfo = DeviceData.fileInfo;
    let device = DeviceData.device;
    // parentPort.postMessage({ event: 'Logcat_info', data: 'Devices : ' + device.MAC + ',IP : ' + device.ip + ' Upload upgrade package' })
    parentPort.postMessage({
      event: "Logcat_info_t",
      data: { mac: device.MAC, ip: device.ip, t: "tip.UUP" },
    });
    if (device.devtype === "3") {
      //需要等待设备响应，设备不能同时处理多个
      await axios.post(
        "http://" + device.ip + "/web.fcgi?",
        " function=doMountMemoryToFlash"
      );
    }
    var localFile = fs.createReadStream(fileInfo.filePath);
    var formData = new FormData();
    formData.append("fileToUpload", localFile);
    var headers = formData.getHeaders(); //获取headers
    //获取form-data长度
    formData.getLength(async function (err, length) {
      if (err) {
        parentPort.postMessage({
          event: "Logcat_error_t",
          data: { mac: device.MAC, ip: device.ip, t: "tip.UUPE" },
        });
        parentPort.postMessage({
          event: "console",
          data: "formData.getLength err :  " + err,
        });
        reject();
      }
      //设置长度，important!!!
      headers["content-length"] = length;
      const options = {
        hostname: device.ip,
        port: 80,
        path: "/web.fcgi?suffix=bin&type=2&storageway=0",
        method: "POST",
        headers: headers,
      };
      const req = http.request(options, (res) => {
        let responseData = "";
        res.on("data", (chunk) => {
          responseData += chunk.toString();
        });
        res.on("end", () => {
          parentPort.postMessage({
            event: "console",
            data: `statusCode: ${device.ip}, ${res.statusCode}`,
          });
          if (res.statusCode == 200) {
            parentPort.postMessage({
              event: "Logcat_success_t",
              data: { mac: device.MAC, ip: device.ip, t: "tip.UUPS" },
            });
            resolve();
          } else {
            parentPort.postMessage({
              event: "Logcat_error_t",
              data: { mac: device.MAC, ip: device.ip, t: "tip.UUPE" },
            });
            reject();
          }
        });
      });
      formData.pipe(req);
      req.on("error", (error) => {
        parentPort.postMessage({
            event: "console",
            data: `req.on(error): ${device.ip}, ${error}`,
          });
        parentPort.postMessage({
          event: "Logcat_error_t",
          data: { mac: device.MAC, ip: device.ip, t: "tip.UUPE" },
        });
        reject();
      });
      localFile.on("end", () => {
        req.end();
      });
    });
  });
};

const GetUpgradeStatus = async function (DeviceData) {
  return await new Promise((resolve, reject) => {
    let MyInterval = null;
    let device = DeviceData.device;
    let RequireFailCnt = 0;
    parentPort.postMessage({
      event: "Logcat_success_t",
      data: { mac: device.MAC, ip: device.ip, t: "tip.SU" },
    });
    MyInterval = setInterval(() => {
      axios({
        url:
          "http://" +
          device.ip +
          "/json/updating_state.json?date=" +
          new Date().getTime(),
        method: "get",
      })
        .then((res) => {
          let data = res.data;
          if (data.state === "bin_fail") {
            var uploadret = "Upload error: verify upgrade package failed!";
            parentPort.postMessage({
              event: "console",
              data: "state error :  " + uploadret,
            });
            hideUploadStatusDivAndReboot();
          } else if (data.state === "check_mainapp_fail") {
            var uploadret =
              "Upload error: verify the main program is failed, please contact the administrator!";
            parentPort.postMessage({
              event: "console",
              data: "state error :  " + uploadret,
            });
            hideUploadStatusDivAndReboot();
          } else if (data.state === "none") {
            RequireFailCnt++;
          } else if (
            data.state === "complete" ||
            data.state === "check_complete"
          ) {
            parentPort.postMessage({
              event: "console",
              data: `updating_state :  ${device.ip} : ${data.state}`,
            });
            clearInterval(MyInterval);
            parentPort.postMessage({
              event: "Logcat_success_t",
              data: { mac: device.MAC, ip: device.ip, t: "tip.USUC" },
            });
            resolve();
          }
        })
        .catch((res) => {
          RequireFailCnt++;
          parentPort.postMessage({
            event: "console",
            data: "updating_state catch res :  " + res.message,
          });
        })
        .finally(() => {
          if (RequireFailCnt >= 200) {
            hideUploadStatusDivAndReboot();
          }
        });
    }, 1000);
    function hideUploadStatusDivAndReboot() {
      clearInterval(MyInterval);
      var uploadret = "verify the main program is failed !";
      parentPort.postMessage({
        event: "Logcat_error",
        data:
          "Devices : " +
          device.MAC +
          ",IP : " +
          device.ip +
          " Upgrade status : " +
          uploadret,
      });

      reject();
    }
  });
};

parentPort.on("message", (poolData) => {
  checkUpdateInfo(poolData)
    .then((res) => {
      uploadUpdateFile(poolData)
        .then((res) => {
            parentPort.postMessage({ event: "done", data: Results.Success });
        //   GetUpgradeStatus(poolData)
        //     .then(() => {
        //       parentPort.postMessage({ event: "done", data: Results.Success });
        //     })
        //     .catch(() => {
        //       parentPort.postMessage({ event: "done", data: Results.Error });
        //     });
        })
        .catch(() => {
          parentPort.postMessage({ event: "done", data: Results.Error });
        });
    })
    .catch((err) => {
      parentPort.postMessage({ event: "done", data: Results.Error });
    });
});
