import {getAllMethods, logs, sleep, sliceChunk} from "@/utils/util";

/**
 *
 */
export class Base {
  constructor(topClass, usbSerial) {
    this.topClass = topClass
    this.usbSerial = usbSerial

    this.title = '设备名'
    this.id = null
    this.k = null
    this.key = null
    this.open = false
    this.auth = false
    this.config = {
      baudRate: 9600,
      dataBits: 8,
      stopBits: 1,// 停止位 1: STOP_BITS_1 2: STOP_BITS_2 3: STOP_BITS_15
      parity: null, // 校验位 0: PARITY_NONE 1: PARITY_ODD 2: PARITY_EVEN 3: PARITY_MARK 4:PARITY_SPACE
      flowControl: null, // 流控 0: FLOW_CONTROL_OFF 1: FLOW_CONTROL_RTS_CTS 2: FLOW_CONTROL_DSR_DTR 3: FLOW_CONTROL_XON_XOFF
    }

    this.notifyFun = null

    this.startChar = 0x02;
    this.endChar = 0x03;
    this.buffer = new Uint8Array(0); // 初始化空的Uint8Array作为缓冲区
  }

  setWatch(fun = null) {
    this.notifyFun = fun
  }

  async _init(k, key) {
    // logs('ScanMachine init')
    if (!key) {
      return;
    }
    if (this.key && this.open) {
      await this.close()
      await sleep(800)
    }
    this.k = k
    this.key = key
    await this.connect()
    // logs('ScanMachine init2')
  }


  async connect() {
    // logs('base connect', this.key || '-', this.open || '-')
    return new Promise(async (resolve, reject) => {
      if (!this.key || (this.key && this.open)) return reject('设备已启动')
      try {
        let option = Object.assign(this.config, {
          key: this.key,
          open: () => {
            this.openHandle()
            // logs('扫码器开始监听')
            resolve()
          },
          read: this.read.bind(this)
        })
        await this.usbSerialHandle(option)
      } catch (e) {
        reject(e)
        console.error('bmiMachine error', e)
      }
    })
  }


  read(resp) {
  }


  openHandle() {
    this.open = true
  }


  async close() {
    if (!this.open) return;
    await this.usbSerial.syncClose({
      key: this.key
    });
    this.auth = false
    this.key = null
    this.open = false

    uni.$emit('machineUsb', {
      id: this.id,
      up: false,
    })
  }


  async usbSerialHandle(option = {}) {
    let op = {
      key: option.key || null,
      baudRate: option.baudRate || 9600,
      dataBits: option.dataBits || 8,
      stopBits: option.stopBits || 1,
      open: option.open || null,
      read: option.read || null,
    }
    if (!op.key) throw '无法监听，请确认参数key'
    if (!this.auth) throw '未授权无法监听'
    try {
      // await this.usbSerial.requestPermission({
      //   key: op.key,
      // });
      // logs('start requestPermission')
      // await sleep(5000)
      // logs('start 1')
      this.usbSerial.open({
        key: op.key,
      })
      await sleep(100)
      // logs('start 2')
      this.usbSerial.setBaudRate({
        key: op.key,
        value: op.baudRate,
      });
      // await sleep(100)
      // logs('start 3')

      this.usbSerial.setDataBits({
        key: op.key,
        value: op.dataBits,
      });
      // await sleep(100)
      // logs('start 4')

      this.usbSerial.setStopBits({
        key: op.key,
        value: op.stopBits,
      });
      // await sleep(100)
      // logs('start 5')

      if (op.parity) this.usbSerial.setParity({
        key: op.key,
        value: op.parity,
      });
      // await sleep(100)
      // logs('start 5')

      if (op.parity) this.usbSerial.setFlowControl({
        key: op.key,
        value: op.flowControl,
      });
      await sleep(500)
      // logs('start 6')

      this.usbSerial.read({
        key: op.key
      }, (resp) => {
        if (!resp.data) return;
        op.read(resp)
      });
      if (op.open) op.open()
      logs('开始监听', this.id, this.key, this.title)
    } catch (e) {
      // console.error('start error', e)
      throw e
    }
  }


  setPacket(startChar = 0x02, endChar = 0x03) {
    this.startChar = startChar
    this.endChar = endChar
  }

  packetManager(data) {
    if (!data) return;
    if (typeof data === 'string') {
      // 如果输入是字符串，将其转换为ASCII码数组
      data = sliceChunk(data, 2)
    }
    // logs('data', data)
    // 将新接收到的数据追加到现有缓冲区
    let tempBuffer = new Uint8Array(this.buffer.length + data.length);
    tempBuffer.set(this.buffer, 0);
    tempBuffer.set(data, this.buffer.length);
    this.buffer = tempBuffer;
    // logs('this.buffer', this.buffer)

    let packets = [];
    let start = 0;
    let end = 0;

    // 循环查找完整的数据包
    while ((start = this.buffer.indexOf(this.startChar, end)) !== -1 && (end = this.buffer.indexOf(this.endChar, start + 1)) !== -1) {
      // 提取从开始字符到结束字符的数据包
      const packet = this.buffer.slice(start, end + 1);
      // logs('packet', packet)
      packets.push(this.bufferTOString(packet));

      // 更新处理后的缓冲区内容
      this.buffer = this.buffer.slice(end + 1);
    }
    // logs('packets', packets)
    if (!packets) return false
    // logs('packets2', packets)

    // 返回所有找到的完整数据包
    return packets;
  }

  bufferTOString(buffer) {
    const hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
        return ('00' + bit).slice(-2).toUpperCase()
      }
    )
    return hexArr.join('')
  }

  parsePacket(packet) {
    if (packet[0] === this.startChar && packet[packet.length - 1] === this.endChar) {
      // 解析数据包内容，这里仅返回去除开始和结束字符的内容
      const content = packet.slice(1, -1);
      return content; // 返回解析后的内容
    } else {
      throw new Error('Invalid packet format.');
    }
  }

}
