/**
 * 沃特沃德串口屏协议服务
 *
 * 版本:v0.1
 * 开发者
 * 历史:
 *
 */

/**
 * 串口协议格式说明:
 *
 * 大端格式(包括参数内容也使用大端)
 *
 * 协议头:0x8081
 * 数据长度:2字节,不包括协议头和数据长度本身
 * 函数码:1字节,函数api索引
 * 参数个数:1字节
 * 参数内容:
 * {
 *   参数类型:1字节,0=int32,1=float,2=double,3=字符串对象(字符串对象包括2字节的长度和内容,utf8格式,0结尾,长度包括0终止符)
 * }
 * crc校验:2字节
 *
 *
 * 返回数据格式:与发送数据格式相同,只是参数个数只能为1个。
 */

// console.log = function () {};
// console.trace = function () {};
var lvgl = require("@native.lvgl7");
var router = require("@system.router");
var process = require("@system.process");
var dpkt = require("dpkt.js");
var wwProto = globalThis["@native.ww"];
var image = require("@native.image");
var librtc = require("rtc.js");
var os = require("@system.os");
var rebootdevice = require("rebootdevice.js");
//nodejs调试模式
var NodeJs = 0;
// 当前页面ID
var g_pageNum;

var WW_POINT_RATE = 0.69;
var WW_POINT_LINE_X = 0.2;
var WW_POINT_LINE_B = -0.8;
var WW_POINT_NUM = 8;
var WW_FONT_RATE = 1.0;
var WW_FONT_HIGHT = 1.2;
var WW_TEXTINPUT_TOP = -5;

var WW_TOPEquation_A = 0.0078125; // 1/128
var WW_TOPEquation_B = -0.40625; // -13/32
var WW_TOPEquation_C = 7.25; // 29/4
var WW_TOPEquation_D = -40; // -40

//后面可以配置参数
var opt_clear_all_images = true;

function checkDialogState() {
  if (isDialogShowing == 2) {
    var pageName = keyboardRule["keyboardId"];
    restoreDataInputPosition();
    router.hideDialog("page" + pageName);
  }
}
function onShow() {
  // console.log("{onShow} debug pos 0 " + isDialogShowing);
  this.$onShow();
  // console.log("{onShow} debug pos 1 ");
  if (opt_clear_all_images && isDialogShowing != 1) {
    // console.log("{onShow} debug pos 2 ");
    var imageCache = this.$imageCache;
    var keys = Object.keys(imageCache);
    for (var i = 0; i < keys.length; i++) {
      var path = keys[i];
      var img_dsc_t = imageCache[path];
      if (!invoke_is_null(img_dsc_t)) {
        image.freeImage(img_dsc_t);
        imageCache[path] = undefined;
      }
    }
  }
  // console.log("{onShow} debug pos 3 ");
  // console.log("{push page} 1");
  var nodes = this.$el;
  if (Array.isArray(nodes)) {
    // console.log("{onShow} debug pos 4 ");
    // console.log("{push page} 2");
    var length = nodes.length;
    for (var i = 0; i < length; i++) {
      // console.log("{push page}i=" + i);
      var node = nodes[i];
      var attributes = node.attributes;
      // console.log("{push page}id=" + attributes.id);
      if (node.name == "image") {
        // console.log("{push page} image");
        var obj = node.nativePtr;
        var widgetType = attributes.widgetType;
        if (widgetType == "varIcon") {
          // console.log(
          //   "{push page}id=" +
          //     attributes.id +
          //     " is var icon,path=" +
          //     attributes.src
          // );
          os.setBlackAsTransparent(true);
        }
        var imageCache = this.$imageCache;
        // console.log("cache keys=" + Object.keys(imageCache));
        // console.log("cache values=" + Object.values(imageCache));
        this.$image_set_src(obj, attributes.src);
        this.$setBackgroundColor(attributes.id, "transparent");
        this.$show(attributes.id);
        os.setBlackAsTransparent(false);
      }
    }
  }
  // console.log("{onShow} debug quit ");
}

var pagePushing = 0;
var router_push = router.push;
router.router_push = router_push;
router.push = function (obj, backend) {
  // console.log("{router push} enter.. ");
  checkDialogState();
  // console.log("{router_push} debug pos 0 ");
  pagePushing = 1;
  this.router_push(obj, backend);
  // console.log("{router_push} finished ");

  if (this.currentPage.$indexObj.$onShow == undefined) {
    var tempOnShow = this.currentPage.$indexObj.onShow;
    this.currentPage.$indexObj.$onShow = tempOnShow;
    this.currentPage.$indexObj.onShow = onShow;
  }

  pagePushing = 0;
  // console.log("{router_push} quit.. ");
};

var adjustKeyboardCoorId = undefined;

var dialog_obj = lvgl.lv_cont_create(lvgl.lv_scr_act(), null);
lvgl.lv_obj_set_style_local_border_width(dialog_obj, 0, 0, 0);
var isDialogShowing = 0;
router.showDialog = function (pageName, x, y, width, height, moveX, moveY) {
  isDialogShowing = 1;
  var page = router.pages[pageName];
  if (page == undefined) {
    opt_clear_all_images = false;
    router.push(
      {
        path: pageName,
      },
      false
    );
    opt_clear_all_images = true;
  }
  isDialogShowing = 2;
  page = router.pages[pageName];
  if (page == undefined) return;

  var nodes = page.$indexObj.$el;
  if (Array.isArray(nodes)) {
    var length = nodes.length;
    for (var i = 0; i < length; i++) {
      var node = nodes[i];
      var attributes = node.attributes;
      if (node.name == "image") {
        var obj = node.nativePtr;
        page.$indexObj.$image_set_src(obj, attributes.src);
      }
    }
  }

  // var rootObj = page.rootObj;
  // lvgl.lv_obj_move_foreground(rootObj);
  // lvgl.lv_obj_set_hidden(rootObj, false);
  // // console.log("x=" + x);
  // // console.log("y=" + y);
  // lvgl.lv_obj_set_left(rootObj, x);
  // lvgl.lv_obj_set_top(rootObj, y);
  page.$indexObj.onShow();

  // adjustKeyboardCoorId = setTimeout(adjustKeyboardCoor, 10, [pageName, width, height, moveX, moveY])
  adjustKeyboardCoorId = setTimeout(function () {
    var router = require("@system.router");
    page = router.pages[pageName];
    // // console.log("pageName=" + pageName);
    // // console.log("page:" + Object.keys(page));
    var indexObj = page.$indexObj;
    // // console.log("indexObj:" + Object.keys(indexObj));
    // var elementList = indexObj.$el
    // console.log("elementList:" + elementList)

    //example:
    lvgl.lv_obj_set_parent(dialog_obj, router.currentPage.$indexObj.$rootObj);
    lvgl.lv_obj_set_x(dialog_obj, x); // do it yourself
    lvgl.lv_obj_set_y(dialog_obj, y); // do it yourself
    // // console.log("width=" + width);
    // // console.log("height=" + height);
    lvgl.lv_obj_set_width(dialog_obj, width); // do it yourself
    lvgl.lv_obj_set_height(dialog_obj, height); // do it yourself

    lvgl.lv_obj_set_parent(page.$indexObj.$rootObj, dialog_obj);
    // // console.log("moveX=" + moveX);
    // // console.log("moveY=" + moveY);
    lvgl.lv_obj_set_x(page.$indexObj.$rootObj, moveX); // do it yourself
    lvgl.lv_obj_set_y(page.$indexObj.$rootObj, moveY); // do it yourself
    // lvgl.lv_obj_set_x(page.$indexObj.$rootObj, 0);// do it yourself
    // lvgl.lv_obj_set_y(page.$indexObj.$rootObj, 0);// do it yourself
    lvgl.lv_obj_move_foreground(page.$indexObj.$rootObj);
    lvgl.lv_obj_move_foreground(dialog_obj);
    lvgl.lv_obj_set_hidden(dialog_obj, false);
    lvgl.lv_obj_set_hidden(page.$indexObj.$rootObj, false);
    lvgl.lv_obj_invalidate(dialog_obj);

    // if (elementList) {
    //     var nodes = page.$indexObj.$nodes;
    //     if (Array.isArray(nodes)) {
    // console.log("Array.isArray(nodes)")
    //         var length = nodes.length;
    //         for (var i = 0; i < length; i++) {
    //             var node = nodes[i];
    //             var attributes = node.attributes;
    // console.log("node id=" + node.attributes.id)
    //             if (node.name == 'image') {
    //                 // var  id=node.attributes["id"]
    //                 // indexObj.$foreground(id)
    //                 // indexObj.$imageRender(id, attributes.src)
    //                 var obj = node.nativePtr;
    //                 indexObj.$image_set_src(obj, attributes.src);
    //                 if (attributes.var_address == "0xFFFF") {
    // console.log("moveX=" + moveX)
    // console.log("moveY=" + moveY)
    //                     indexObj.$setX(attributes.id, moveX)
    //                     indexObj.$setY(attributes.id, moveY)
    //                 }
    //             }
    //             if (attributes.id == pageName) {
    // console.log("width=" + width)
    // console.log("height=" + height)
    //                 indexObj.$setWidth(attributes.id, width)
    //                 indexObj.$setHeight(attributes.id, height)
    //             }
    //         }
    //     }
    // }
    clearTimeout(adjustKeyboardCoorId);
    // // console.log("=========showDialog quit..");
  }, 50);
};

router.hideDialog = function (pageName) {
  // // console.log("pageName:" + pageName);
  isDialogShowing = 0;
  var page = router.pages[pageName];
  if (page == undefined) return;
  page.$indexObj.onHide();
  var rootObj = page.rootObj;
  lvgl.lv_obj_set_hidden(rootObj, true);
  lvgl.lv_obj_move_background(rootObj);
  lvgl.lv_obj_set_hidden(dialog_obj, true);

  updatePageDataId = setTimeout(function () {
    refreshPageMessage();
    clearTimeout(updatePageDataId);
  }, 50);
};

function initEventLister() {
  var EventEmitter = require("@system.events");
  globalThis.eventEmitter = new EventEmitter();
}
initEventLister();

/**windows下调试配置
 * 1、串口号
 */
var winDefaultPort = "COM4";
var uartWW = undefined;

function TextDecoder(encoding) {
  if (encoding == undefined) this.encoding = "utf-8";
  else this.encoding = encoding;
}

TextDecoder.prototype.decode = function (data) {
  var os = require("@system.os");
  return os.decode(this.encoding, data.cdata(), data.length);
};

var ww_regs;

/**
 *  串口设置相关
 */
function setup(port, baud) {
  //读取配置文件
  var cfg = loading(__dirname + "/config.json");
  if (cfg != undefined) {
    for (var cnt = 0; cnt < cfg.module.length; cnt++) {
      var req = require(cfg.module[cnt].file);
      if (cfg.module[cnt].param != undefined) {
        req.init(cfg.module[cnt].param);
      } else {
        req.init();
      }
    }
  }
  //串口打开后,解析数据协议,调用protoHandler
  var uart = require("uart.js");
  if (process.platform == "win32") {
    port = winDefaultPort;
    console.log("port=" + port);
    console.log("baud=" + baud);
    uartWW = uart.open({
      path: port,
      baudRate: baud,
      dataBits: 8,
      stopbits: 1,
      parity: 0,
      mode: "text", // mode="text/json/bin"
    });

    setInterval(function () {
      uartWW.read();
    }, 100);
  } else {
    console.log("port=" + port);
    console.log("baud=" + baud);
    uartWW = uart.open_async({
      path: port,
      baudRate: baud,
      dataBits: 8,
      stopbits: 1,
      parity: 0,
      mode: "text",
      timeout: 10,
    });
  }
  uartWW.on("data", getUartData);
}

/**
 *  收到串口数据
 */
function getUartData(data, length) {
  if (data.length == 0) {
    // data.print()
    data.free();
    return;
  }
  // console.log(showMemInfo())
  data.print();
  var currentPage = router.currentPage;
  if (currentPage == undefined) {
    wwProto.handle(undefined, data.cdata(), data.length, handleCallback);
    data.free();
    return;
  }

  var indexObj = currentPage.$indexObj;
  wwProto.handle(indexObj, data.cdata(), data.length, handleCallback);
  data.free();
}

var funcAPIs = undefined;
var cached_values = undefined;

function push_page(pageId) {
  router.push({
    path: "page" + pageId,
  });
}

function push_page_and_refresh_caches(pageId) {
  var currentPage = router.currentPage;
  router.push({
    path: "page" + pageId,
  });
  var indexObj = currentPage.$indexObj;
  for (var i in cached_values) {
    var value = cached_values[i];
    var funcId = value["funcId"];
    var args = value["args"];
    funcAPIs[funcId].apply(indexObj, args);
  }
  cached_values = undefined;
}

function write_cache(funcId, args) {
  if (cached_values == undefined) {
    cached_values = [];
  }
  cached_values.push({
    funcId: funcId,
    args: [args],
  });
}
function efix_show(elementId) {
  var currentPage = router.currentPage;
  var indexObj = currentPage.$indexObj;
  indexObj.$show(elementId);
  indexObj.$foreground(elementId);
}
function buttonGetKey(elementId) {
  var currentPage = router.currentPage;
  var indexObj = currentPage.$indexObj;
  var element = indexObj.$getElementById(elementId);
  var res = 0;
  if (element) {
    res = element.attributes.KeySet;
  }
  return res;
}
function buttonSetKey(elementId, value) {
  var currentPage = router.currentPage;
  var indexObj = currentPage.$indexObj;
  var element = indexObj.$getElementById(elementId);
  if (element) {
    element.attributes.KeySet = value;
  }
}

function systemGetRunState() {
  return 1;
}
function qrcodeSetSrc(id, src) {
  var currentPage = router.currentPage;
  var indexObj = currentPage.$indexObj;
  var obj = indexObj.$getElementPtrById(id);
  if (obj == undefined) return;
  var lvgl = require("@native.lvgl7");
  lvgl.lv_qrcode_set_value(obj, src);

  var element = indexObj.$getElementById(id);
  element.attributes.value = src;
}
function qrcodeGetSrc(id, src) {
  var currentPage = router.currentPage;
  var indexObj = currentPage.$indexObj;
  var element = indexObj.$getElementById(id);
  if (element == undefined) return;
  var res = element.attributes.value;
  return res;
}

function start_test(args){
  console.log('==='+args )
}

function reboot_device(rebootnum){
  if (rebootnum=="1"){
    console.log('==='+rebootnum )
    rebootdevice.reboot()
  }
}
function handleCallback(indexObj, funcId, args) {
  console.log("{ Get } funcId=" + funcId + " args=" + args);
  // console.log(typeof args);
  if (indexObj == undefined) {
    console.log("ERROR!indexObj is undefined..");
    return;
  }
  if (funcAPIs == undefined) {
    funcAPIs = [
      indexObj.$getX, //0: 获取x坐标
      indexObj.$setX, //1: 设置x坐标
      indexObj.$getY, //2: 获取y坐标
      indexObj.$setY, //3: 设置y坐标
      indexObj.$getWidth, //4:获取宽度
      indexObj.$setWidth, //5:设置宽度
      indexObj.$getHeight, //6:获取高度
      indexObj.$setHeight, //7:设置高度
      indexObj.$setPos, //8:设置x,y
      indexObj.$setSize, //9:设置宽高
      indexObj.$setOpacity, //10: 设置透明度
      indexObj.$setBackgroundColor, //11:设置背景颜色
      indexObj.$setText, //12:设置文本
      indexObj.$getText, //13:获取文本
      indexObj.$setTextColor, //14:设置文本颜色
      indexObj.$setTextOpacity, //15:获取文本颜色
      indexObj.$setTextFontSize, //16:设置文本字体大小
      indexObj.$setImageAngle, //17:设置图片旋转角度
      indexObj.$setImageZoom, //18:设置图片缩放
      indexObj.$setSliderValue, //19:设置滑动条位置
      indexObj.$getSliderValue, //20:获取滑动条位置

      push_page, //21:跳转页面
      // push_page_and_refresh_caches, //22,跳转页面并立即刷新缓存
      // write_cache, //23,写缓存
      // indexObj.$show, //24:显示
      efix_show, //22:显示
      indexObj.$hide, //23:隐藏
      indexObj.$imageRender, //24:设置图片控件图片源
      buttonGetKey, //25:获取按钮键值
      buttonSetKey, //26:设置按钮键值
      systemGetRunState, //27:系统功能 查询运行状态
      qrcodeGetSrc, //28 获取二维码内容
      qrcodeSetSrc, //29 设置二维码内容
      start_test,//30  开始
      reboot_device,//31 重启
    ];
  }
  console.log("{ Server } funcName=" + funcAPIs[funcId]);
  var res = funcAPIs[funcId].apply(indexObj, args);
  console.log("{ Server } funcRes=" + res);

  //这里处理回复数据
  var resArr = wwProto.response(res, funcId);
  var resU8Arr = new Uint8Array(resArr);
  var resBinArr = Buffer.from(resU8Arr);

  console.log("{ Resp } binBuffer");
  resBinArr.print();
  uartWW.write(resBinArr);
  resBinArr.free();
  console.log("{ Get } End.");
}
function reportData(res, funcId) {
  var resArr = wwProto.response(res, funcId);
  var resU8Arr = new Uint8Array(resArr);
  var resBinArr = Buffer.from(resU8Arr);

  uartWW.write(resBinArr);
  resBinArr.free();
}
//inline

//读取配置文件函数
function loading(filePath) {
  console.log("loading");
  if (checkFile(filePath)) {
    return loadDataByJson(filePath);
  }
  return undefined;
}
function checkFile(name) {
  console.log("checkFile " + name);
  if (NodeJs) {
    var fs = require("fs");
    if (fs.existsSync(name)) {
      return 1;
    } else {
      return 0;
    }
  } else {
    //使用系统file操作
    var fs = require("@system.fs");
    //检测文件是否存在
    if (fs.exists(name)) {
      return 1;
    } else {
      return 0;
    }
  }
}
function loadDataByJson(name) {
  console.log("loadDataByJson " + name);
  if (NodeJs) {
    var fs = require("fs");
    var fdata = fs.readFileSync(name, "utf-8");
    var ret = JSON.parse(fdata);
  } else {
    //使用系统file操作
    var fs = require("@system.fs");
    var fdata = fs.readFile(name);
    var ret = JSON.parse(fdata);
  }
  return ret;
}

//extern
function touchClick(node) {
  var type = node.attributes.widgetType;
  console.log("==touchClick:type=" + type);
  // touchElementClickCallback[type](node);
  node.attributes.KeySet = node.attributes.KeyCode;
}
function refreshPageMessage() {}

function start_senddata(){
  var resArr = wwProto.response(undefined, 30);
  var resU8Arr = new Uint8Array(resArr);
  var resBinArr = Buffer.from(resU8Arr);

  console.log("{ Resp } binBuffer");
  resBinArr.print();
  uartWW.write(resBinArr);
  resBinArr.free();
  console.log("{ Get } End.");
  console.log("***************************")
}

var  setTimeoutdata=setTimeout(function () {
  start_senddata();
  clearTimeout(setTimeoutdata);
}, 500);
module.exports = {
  setup: setup,
  touchClick: touchClick,
  refreshPageMessage: refreshPageMessage,
  reportData: reportData,
};