'use strict';

const path = require('path');
const fs = require('fs');
const { exec } = require('child_process');
const { Controller } = require('ee-core');
const { app: electronApp, shell } = require('electron');
const dayjs = require('dayjs');
const Ps = require('ee-core/ps');
const Log = require('ee-core/log');
const Services = require('ee-core/services');
const Conf = require('ee-core/config');
const Addon = require('ee-core/addon');
const EE = require('ee-core/ee');
const { getNetworkIFaceOne, getMac, getAllMac, getAllPhysicsMac } = require('@lzwme/get-physical-address');
const os = require('os');
// 网络
const net = require('net');
// 串口
const { SerialPort } = require('serialport')
// 保存串口实例
var GlobalSeriaPortIns = undefined;
/**
 * electron-egg framework - 功能demo
 * @class
 */
class FrameworkController extends Controller {

  constructor(ctx) {
    super(ctx);
  }

  /**
   * 所有方法接收两个参数
   * @param args 前端传的参数
   * @param event - ipc通信时才有值。详情见：控制器文档
   */




  /**
    * 发送串口消息
    * @param {*} seriaPort 串口实例
    */
  sendSeriaPort(args) {
    const port = GlobalSeriaPortIns;
    const msg = args.msg;
    port.write(msg, 'hex')
    // console.log('测试发送消息'+msg);
  }
  /**
   * 连接串口 只执行一次
   * @param {*} options 串口参数
   * @param {*} event 回调. 
   */
  connectSeriaPort(options, event) {

    // 保证执行一次
    if (GlobalSeriaPortIns != undefined) {
      console.log("SerialPort is have");
      return;
    }
    const channel = 'controller.hardware.connectSeriaPort';
    const port = new SerialPort(options, (e) => {
      console.log("SerialPort open");
      console.log(e);
      if (e === null) {
        // 打开成功 把串口发送出去
        let data2 = {
          type: 'connect'
        }
        event.reply(`${channel}`, data2)
      }

    })

    port.on('data', (data) => {
      let data2 = {
        type: 'received',
        data: data
      }
      console.log(`Received data: ${data2}`)
      event.reply(`${channel}`, data2)
    })
    setInterval(() => {
      // console.log('setInterval')
      if (!port.isOpen) {
        // console.log('setInterval open')
        port.open();
      }

    }, 1000)
    port.on('close', () => {
      let data2 = {
        type: 'close'
      }
      console.log(`SerialPort close: ${data2}`)
      event.reply(`${channel}`, data2)
    })
    port.on('error', (e) => {
      let data2 = {
        type: 'error'
      }
      console.log(`SerialPort error: ${e}`)
      event.reply(`${channel}`, data2)
    })

    GlobalSeriaPortIns = port;

  }

  /**
  * 发送tcp 消息
  * @param {*} args  包含host port msg type { 1 hex, 2 ascii}
  * @param {*} event 
  */
  sendTcpSocket(args, event) {
    const channel = 'controller.example.sendTcpSocket';
    console.log("tcp params")
    console.log(args);
    const client = new net.Socket();
    // client.setEncoding('ascii');
    const HOST = args.host;
    const PORT = args.port;
    const msg = args.msg;

    // const HOST = '192.168.5.134';
    // const PORT = 9080;
    client.connect(PORT, HOST, function () {
      console.log('Connected to: ' + HOST + ':' + PORT);
    });

    client.on('data', function (data) {
      console.log('Received: ' + data);
      event.sender.send(`${channel}`, data);
    });
    //两种码的发送 ok
    // client.write('Hello, server!','ascii');
    if (args.type == 1) {
      client.write(msg, 'hex');
    } else {
      client.write(msg, 'ascii');
    }

    client.on('close', function () {
      console.log('Connection closed');
    });
    client.end();

  }



  /**
     * 获取extraResources 目录下的json 配置文件
     * @param {*} name  配置文件名
     * @returns  返回json 字符传
     */
  getExResConfig(name) {
    let configPath = path.join(Ps.getExtraResourcesDir(), name);;

    console.log(configPath)
    // let configJSON = null;
    let dataString = null;
    try {
      // 同步读取配置文件
      dataString = fs.readFileSync(configPath, 'utf8');

      // 解析 JSON 格式的配置数据
      // configJSON = JSON.parse(data);
      // console.log('读取到的配置:', configJSON);

      // 在这里可以根据需要使用配置数据进行操作
    } catch (err) {
      console.error('无法读取配置文件:', err);
    }
    return dataString;
  }



  /**
   * json数据库操作
   */
  async jsondbOperation(args) {
    const { action, info, delete_name, update_name, update_age, search_age, data_dir } = args;

    const data = {
      action,
      result: null,
      all_list: []
    };

    switch (action) {
      case 'add':
        data.result = await Services.get('database.jsondb').addTestData(info);
        break;
      case 'del':
        data.result = await Services.get('database.jsondb').delTestData(delete_name);
        break;
      case 'update':
        data.result = await Services.get('database.jsondb').updateTestData(update_name, update_age);
        break;
      case 'get':
        data.result = await Services.get('database.jsondb').getTestData(search_age);
        break;
      case 'getDataDir':
        data.result = await Services.get('database.jsondb').getDataDir();
        break;
      case 'setDataDir':
        data.result = await Services.get('database.jsondb').setCustomDataDir(data_dir);
        break;
    }

    data.all_list = await Services.get('database.jsondb').getAllTestData();

    return data;
  }

  /**
   * sqlite数据库操作
   */
  async sqlitedbOperation(args) {
    const { action, info, delete_name, update_name, update_age, search_age, data_dir } = args;

    const data = {
      action,
      result: null,
      all_list: [],
      code: 0
    };

    try {
      // test
      Services.get('database.sqlitedb').getDataDir();
    } catch (err) {
      console.log(err);
      data.code = -1;
      return data;
    }

    switch (action) {
      case 'add':
        data.result = await Services.get('database.sqlitedb').addTestDataSqlite(info);;
        break;
      case 'del':
        data.result = await Services.get('database.sqlitedb').delTestDataSqlite(delete_name);;
        break;
      case 'update':
        data.result = await Services.get('database.sqlitedb').updateTestDataSqlite(update_name, update_age);
        break;
      case 'get':
        data.result = await Services.get('database.sqlitedb').getTestDataSqlite(search_age);
        break;
      case 'getDataDir':
        data.result = await Services.get('database.sqlitedb').getDataDir();
        break;
      case 'setDataDir':
        data.result = await Services.get('database.sqlitedb').setCustomDataDir(data_dir);
        break;
    }

    data.all_list = await Services.get('database.sqlitedb').getAllTestDataSqlite();

    return data;
  }

  /**
   * 调用其它程序（exe、bash等可执行程序）
   */
  openSoftware(softName) {
    if (!softName) {
      return false;
    }

    let softwarePath = path.join(Ps.getExtraResourcesDir(), softName);
    Log.info('[openSoftware] softwarePath:', softwarePath);

    // 检查程序是否存在
    if (!fs.existsSync(softwarePath)) {
      return false;
    }
    // 命令行字符串 并 执行
    let cmdStr = 'start ' + softwarePath;
    exec(cmdStr);

    return true;
  }

  /**
   * 检查是否有新版本
   */
  checkForUpdater() {
    Addon.get('autoUpdater').checkUpdate();
    return;
  }

  /**
   * 下载新版本
   */
  downloadApp() {
    Addon.get('autoUpdater').download();
    return;
  }

  /**
   * 检测http服务是否开启
   */
  async checkHttpServer() {
    const httpServerConfig = Conf.getValue('httpServer');
    const url = httpServerConfig.protocol + httpServerConfig.host + ':' + httpServerConfig.port;

    const data = {
      enable: httpServerConfig.enable,
      server: url
    }
    return data;
  }

  /**
   * 一个http请求访问此方法
   */
  async doHttpRequest() {
    const { CoreApp } = EE;
    // http方法
    const method = CoreApp.request.method;
    // http get 参数
    let params = CoreApp.request.query;
    params = (params instanceof Object) ? params : JSON.parse(JSON.stringify(params));
    // http post 参数
    const body = CoreApp.request.body;

    const httpInfo = {
      method,
      params,
      body
    }
    Log.info('httpInfo:', httpInfo);

    if (!body.id) {
      return false;
    }
    const dir = electronApp.getPath(body.id);
    shell.openPath(dir);

    return true;
  }

  /**
   * 一个socket io请求访问此方法
   */
  async doSocketRequest(args) {
    if (!args.id) {
      return false;
    }
    const dir = electronApp.getPath(args.id);
    shell.openPath(dir);

    return true;
  }

  /**
   * 异步消息类型
   */
  async ipcInvokeMsg(args, event) {
    let timeNow = dayjs().format('YYYY-MM-DD HH:mm:ss');
    const data = args + ' - ' + timeNow;

    return data;
  }

  /**
   * 同步消息类型
   */
  async ipcSendSyncMsg(args) {
    let timeNow = dayjs().format('YYYY-MM-DD HH:mm:ss');
    const data = args + ' - ' + timeNow;

    return data;
  }

  /**
   * 双向异步通信
   */
  async ipcSendMsg(args, event) {
    const { type, content } = args;
    const data = await Services.get('framework').bothWayMessage(type, content, event);

    return data;
  }

  /**
   * 不建议使用，请使用electron的api来获取文件的本机路径，然后读取并上传
   * 使用http的files属性，实际上多余拷贝一次文件
   */  

  async uploadFile() {
    const { CoreApp } = EE;
    let tmpDir = Ps.getLogDir();
    const files = CoreApp.request.files;
    let file = files.file;

    let tmpFilePath = path.join(tmpDir, file.originalFilename);
    try {
      let tmpFile = fs.readFileSync(file.filepath);
      fs.writeFileSync(tmpFilePath, tmpFile);
    } finally {
      await fs.unlink(file.filepath, function () { });
    }
    const fileStream = fs.createReadStream(tmpFilePath);
    const uploadRes = await Services.get('framework').uploadFileToSMMS(fileStream);

    return uploadRes;
  }

  /**
   * 启动java项目
   */
  async startJavaServer() {
    let data = {
      code: 0,
      msg: '',
      server: ''
    }
    const javaCfg = Conf.getValue('addons.javaServer') || {};
    if (!javaCfg.enable) {
      data.code = -1;
      data.msg = 'addon not enabled!';
      return data;
    }

    await Addon.get('javaServer').createServer();

    data.server = 'http://localhost:' + javaCfg.port;

    return data;
  }

  /**
   * 关闭java项目
   */
  async closeJavaServer() {
    let data = {
      code: 0,
      msg: '',
    }
    const javaCfg = Conf.getValue('addons.javaServer') || {};
    if (!javaCfg.enable) {
      data.code = -1;
      data.msg = 'addon not enabled!';
      return data;
    }

    await Addon.get('javaServer').kill();

    return data;
  }

  /**
   * java运行状态
   */
  async runStatus() {
    let data = {
      code: 0,
      msg: '',
      flag: false
    }
    const flag = await Addon.get('javaServer').check();
    //Log.info("[FrameworkController:runStatus] flag-----------"+flag);
    data.flag = flag;

    return data;
  }

  /**
   * 任务
   */
  someJob(args, event) {
    let jobId = args.id;
    let action = args.action;

    let result;
    switch (action) {
      case 'create':
        result = Services.get('framework').doJob(jobId, action, event);
        break;
      case 'close':
        Services.get('framework').doJob(jobId, action, event);
        break;
      default:
    }

    let data = {
      jobId,
      action,
      result
    }
    return data;
  }

  /**
   * 创建任务池
   */
  async createPool(args, event) {
    let num = args.number;
    Services.get('framework').doCreatePool(num, event);

    // test monitor
    Services.get('framework').monitorJob();

    return;
  }

  /**
   * 通过进程池执行任务
   */
  someJobByPool(args, event) {
    let jobId = args.id;
    let action = args.action;

    let result;
    switch (action) {
      case 'run':
        result = Services.get('framework').doJobByPool(jobId, action, event);
        break;
      default:
    }

    let data = {
      jobId,
      action,
      result
    }
    return data;
  }

  /**
   * 测试接口
   */
  hello(args) {
    Log.info('hello ', args);
  }
}

FrameworkController.toString = () => '[class FrameworkController]';
module.exports = FrameworkController;  