import {array_column, logs, sleep} from "@/utils/util";
import * as ASCIIUtils from "@/uni_modules/wrs-js-modbusCRCHex/js_sdk/wrs-ASCIIUtils";
import {ScanMachine} from "@/utils/machine/scanMachine";
import {showToast} from "@/utils/app";
import {usbConfigList} from "@/utils/machine/config";
import {BmiMachine} from "@/utils/machine/bmiMachine";
import Debounce from "@/utils/debounce";

let usbSerial = null
// #ifdef APP-PLUS
usbSerial = uni.requireNativePlugin("wrs-usbSerial")
// logs('usbSerial', usbSerial)

// #endif

export class Machine {


  constructor() {
    this.usbList = []
    this.usbNum = 0


    this.scanMachineClass = null
    this.bmiMachineClass = null

    this.permission = {
      key: null,// usb地址
      status: 0,
      okList: [],// 已申请列表
      list: {},// 记录列表
    }


    this.notify = false
    this.notifyThis = null

    // logs('Machine')
    this.debounce = new Debounce()
    this._init()
  }

  /**
   * @returns {ScanMachine}
   */
  scan() {
    if (!this.scanMachineClass) {
      this.scanMachineClass = new ScanMachine(this, usbSerial)
    }
    return this.scanMachineClass
  }

  /**
   * @returns {BmiMachine}
   */
  bmi() {
    if (!this.bmiMachineClass) {
      this.bmiMachineClass = new BmiMachine(this, usbSerial)
    }
    return this.bmiMachineClass
  }

  async open(types = []) {
    // logs('open')
    for (const k in types) {
      let it = types[k]
      console.log('it', it)
      if (it == 1) {
        // await this.scans()._init()
      }
    }
    await sleep(1000)
    this.getUsbList()
  }

  /**
   * @param open      插入usb 或 拔出usb
   */
  async getUsbList(open = true) {
    this.debounce.do('getUsbList', () => {
      // logs('getUsbList1')
      this.usbList = {};
      this.usbNum = 0
      let that = this
      // #ifdef APP-PLUS
      this.permission.list = {}
      usbSerial.findSerialPortDevice((resp) => {
        logs('getUsbList2', resp)
        if (resp.devices) {
          that.usbList = resp.devices;
          that.usbNum = resp.devices.length
          for (const key in this.usbList) {
            let it = this.usbList[key]
            // logs('it', it)
            const {vendorId, productId} = it.device
            it.k = `${vendorId}_${productId}`
            it.id = usbConfigList[it.k]
            // logs('k', k, it.key, usbConfigList[k])
            if (usbConfigList[it.k]) {
              let data = {
                id: it.id,
                k: it.k,
                key: it.key,
                vendorId,
                productId,
              }
              this.permission.list[data.key] = data
            } else {
              showToast(`未知设备：${key}`)
            }
          }
        }
        // logs('this.usbList', this.usbList)
        // logs('this.permission.list', this.permission.list)
        // logs('this.permission.okList', this.permission.okList)
        if (open) {
          this.getPermission()
        } else {
          this.closeUsb()
        }
      });
      // #endif
    }, 800)

  }


  getOnlineUsb(type = 1) {
    let list = this.permission.okList
    if (type === 1) {
      list = array_column(list, 'id')
    }
    return list
  }


  _init() {
    // logs('machine _init')
    // #ifdef APP-PLUS
    usbSerial.registerReceiver((resp) => {
      const action = resp.action;
      switch (action) {
        // USB授权结果
        case "com.android.wrs.USB_PERMISSION":
          const granted = resp.granted;
          // showToast("USB授权结果:" + granted);
          // logs(1, granted)
          this.getPermission(granted ? 1 : 2)
          break;
        case "android.hardware.usb.action.USB_DEVICE_ATTACHED":
          // logs(2)
          // showToast("有USB设备连接");
          this.getUsbList(true)
          break;
        case "android.hardware.usb.action.USB_DEVICE_DETACHED":
          // showToast("USB设备断开连接");
          this.getUsbList(false)
          // logs(3, resp)
          break;
        default:
          break;
      }
    });
    this.getUsbList()
    // #endif
  }

  async getPermission(type = 0) {
    // logs('getPermission', type)
    const l = Object.values(this.permission.list).length
    // logs('getPermission', type)
    if (l < 1) return false;
    let key = this.permission.key
    if (!key) {
      key = Object.keys(this.permission.list)[0]
      this.permission.key = key
    }
    // logs('key', key)
    let item = this.permission.list[key]
    // logs('getPermission2', this.permission.status, type, item)
    let status = this.permission.status
    // 已授权可跳出
    if (this.permission.okList[item.key]) {
      type = 3 // 已授权直接跳过
      showToast(`已跳出 ${this[item.id]().title} 授权（重复）`, {
        position: 'bottom'
      })
    }

    if (type == 0 && status == 0) {
      usbSerial.requestPermission({
        key: item.key,
      });
      this[item.id]().key = item.key
      this.permission.status = 1
      return;
    }
    // 同意
    if (type == 1) {
      // logs('connect')
      this[item.id]().auth = true
      this[item.id]().connect()
      // logs('connect1')
      this.permission.okList.push({
        key: item.key,
        id: item.id,
      })
      // logs('connect2')
      uni.$emit('machineUsb', {
        id: item.id,
        up: true,
      })
      // logs('connect3')
    }
    // 拒绝
    if (type == 2) {
      showToast(`拒绝了 ${this[item.id]().title} 授权，请重启软件再次授权`)
      await sleep(1000)
      uni.$emit('machineUsb', {
        id: item.id,
        up: false,
      })
    }
    // logs('getPermissiongetPermission', type)
    if (type != 0) {
      delete this.permission.list[item.key]
      this.permission.status = 0
      this.permission.key = null
      await this.getPermission(0)
    }
  }


  closeUsb() {
    // logs('closeUsb')
    let newList = {}
    if (this.usbList.length > 0) {
      newList = array_column(this.usbList, 'id', 'key')
    }
    this.permission.okList = this.permission.okList.filter(it => {
      if (!newList[it.key]) {
        this[it.id]().close();
        return false; // 过滤掉需要删除的元素
      }
      return true; // 保留不需要删除的元素
    });

    logs('closeUsb this.permission.okList', this.permission.okList)
  }

}


