import Utils from './util'
import SM4 from './sm4'
import md5 from 'js-md5'
import Logger from './logger'
import { off } from 'codemirror'
class Request {
  constructor(cmd, payload) {
    this.cmd = cmd
    this.payload = payload
  }
  /**
   * 0x8018 读取身份证信息
   */
  readIDMessage() {
    const buffer = new ArrayBuffer(2)
    const dataView = new DataView(buffer)
    const offset = 0
    dataView.setUint16(offset, this.cmd)

    return new Uint8Array(buffer)
  }
  /**
   * 0x8016 录入人脸
   */
  writeFace() {
    const buffer = new ArrayBuffer(2)
    const dataView = new DataView(buffer)
    const offset = 0
    dataView.setUint16(offset, this.cmd)

    return new Uint8Array(buffer)
  }
  /**
   * 0x8017 录入人脸
   */
  readFace() {
    const buffer = new ArrayBuffer(2)
    const dataView = new DataView(buffer)
    const offset = 0
    dataView.setUint16(offset, this.cmd)

    return new Uint8Array(buffer)
  }
  /**
   * 0x8010 读卡
   */
  readRFCard() {
    const buffer = new ArrayBuffer(2)
    const dataView = new DataView(buffer)
    const offset = 0
    dataView.setUint16(offset, this.cmd)
    return new Uint8Array(buffer)
  }

  /**
   * 0x8011 写卡
   */
  writeRFCard() {
    Logger.info('start writeRFCard')
    const buffer = new ArrayBuffer(51)
    const dataView = new DataView(buffer)
    let offset = 0
    dataView.setUint16(offset, this.cmd)
    offset += 2
    // 明文数据16字节
    // 第一个字节密钥类型 0xff：使用私钥
    dataView.setUint8(offset, this.payload.keyType)
    offset += 1
    // 算法种类
    dataView.setUint8(offset, 0x01)
    offset += 1
    // 对应算法
    dataView.setUint8(offset, 0x01)
    offset += 1
    // 4个字节卡号
    const cardNo = Utils.hexStr2Byte(this.payload.cardNo)
    for (let i = 0; i < 4; i++) {
      dataView.setUint8(offset, cardNo[i])
      offset += 1
    }
    for (let i = 0; i < 9; i++) {
      dataView.setUint8(offset, 0)
      offset += 1
    }
    // 密文数据16字节做sm4加密
    const buffer1 = new ArrayBuffer(23)
    const dataView1 = new DataView(buffer1)
    let offset1 = 0
    // 长度
    dataView1.setUint16(offset1, 20)
    offset1 += 2
    // 卡号
    for (let i = 0; i < 4; i++) {
      dataView1.setUint8(offset1, cardNo[i])
      offset1 += 1
    }
    dataView1.setUint32(offset1, 0)
    offset1 += 4
    // 5个字节的起始时间
    dataView1.setUint8(offset1, 0)
    offset1 += 1
    dataView1.setUint32(offset1, this.payload.startTime)
    offset1 += 4
    dataView1.setUint8(offset1, 0)
    offset1 += 1
    dataView1.setUint32(offset1, this.payload.endTime)
    offset1 += 4
    // 使用次数
    dataView1.setUint8(offset1, this.payload.useCountLimit)

    offset1 += 1
    dataView1.setUint8(offset1, this.payload.index)
    offset1 += 1
    dataView1.setUint8(offset1, this.payload.isLine)
    Logger.info('start sm4 key is ' + Utils.byte2HexStr(this.payload.privateKey))
    const data_origin = new Uint8Array(buffer1)
    const data_enc = SM4.sm4_enc(data_origin, data_origin.length, this.payload.privateKey)
    console.log(data_enc)
    Logger.info('sm4 success ' + Utils.byte2HexStr(data_enc))
    for (let i = 0; i < data_enc.length; i++) {
      dataView.setUint8(offset, data_enc[i])
      offset += 1
    }
    return new Uint8Array(buffer)
  }
  /*
   * 0x8013 录入指纹
   */
  writeFingerPrint() {
    const buffer = new ArrayBuffer(2)
    const dataView = new DataView(buffer)
    const offset = 0
    dataView.setUint16(offset, this.cmd)

    return new Uint8Array(buffer)
  }
  /**
   * 0x8014 读卡
   */
  readFingerPrint() {
    const buffer = new ArrayBuffer(2)
    const dataView = new DataView(buffer)
    const offset = 0
    dataView.setUint16(offset, this.cmd)
    return new Uint8Array(buffer)
  }
}

class Response {
  constructor(payload) {
    this.payload = payload
  }
  //获取身份证信息
  readIDMessage() {
    const array = new Uint8Array(this.payload)
    const dataView = new DataView(array.buffer)
    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)
    if (status !== 0x00) {
      return {
        cmd, cmd,
        status: status
      }
    }
    offset += 1
    const cardType = dataView.getUint8(offset)
    offset += 1
    const IdMsgLen = dataView.getUint16(offset)
    offset += 2
    var idMsg = array.slice(offset, IdMsgLen + offset)
    var idMsgMode = {}
    if (cardType === 0x01) {
      idMsgMode = this.readChinaIDMsg(idMsg)
    }
    offset += IdMsgLen
    const pictureLen = dataView.getUint16(offset)
    offset += 2
    var picture = array.slice(offset, pictureLen + offset)
    const picturehex = Buffer.from(picture).toString('hex')
    offset += pictureLen
    const fpLen = dataView.getUint16(offset)
    offset += 2
    var fp = array.slice(offset, fpLen + offset)
    const fphex = Buffer.from(picture).toString('hex')
    return {
      cmd: cmd,
      status: status,
      cardType: cardType,
      IdMsgLen: IdMsgLen,
      IdMsgMode: idMsgMode,
      pictureLen: pictureLen,
      picture: picturehex,
      fpLen: fpLen,
      fp: fphex
    }

  }
  hexToStr(hex, encoding) {
    var trimedStr = hex.trim();
    var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
    var len = rawStr.length;
    if (len % 2 !== 0) {
      alert("Illegal Format ASCII Code!");
      return "";
    }
    var curCharCode;
    var resultStr = [];
    for (var i = 0; i < len; i = i + 2) {
      curCharCode = parseInt(rawStr.substr(i, 2), 16);
      resultStr.push(curCharCode);
    }
    // encoding为空时默认为utf-8
    var bytesView = new Uint8Array(resultStr);
    var str = new TextDecoder(encoding).decode(bytesView);
    let a = str.replace(/[^0-9]/ig, "");

    return a;
  }

  byte2Chinese(bytes) {
    var val = "";

    for (var i = 0; i < bytes.length; i = i + 2) {
      var aarr = []
      let a = bytes[i]
      let b = bytes[i + 1]
      let c = a
      a = b
      b = c
      aarr.push(a)
      aarr.push(b)
      const hexStr = Buffer.from(aarr).toString('hex')
      val += String.fromCharCode(parseInt(hexStr, 16));

    }
    val = val.replace(/^\s*|\s*$/g, "");
    return val


  }
  readChinaIDMsg(isMsg) {

    let offset = 0
    const byName = isMsg.slice(offset, 30)

    const byNamehex = this.byte2Chinese(byName)


    offset += 30
    const bySex = isMsg.slice(offset, offset + 2)
    const bySexhex1 = Buffer.from(bySex).toString('hex')
    const bySexhex = this.hexToStr(bySexhex1)
    offset += 2
    const byRace = isMsg.slice(offset, offset + 4)
    const byRacehex1 = Buffer.from(byRace).toString('hex')
    const byRacehex = this.hexToStr(byRacehex1)
    offset += 4
    const byBirth = isMsg.slice(offset, offset + 16)
    const byBirthhex1 = Buffer.from(byBirth).toString('hex')
    const byBirthhex = this.hexToStr(byBirthhex1)
    offset += 16
    const byAddress = isMsg.slice(offset, offset + 70)
    const byAddresshex = this.byte2Chinese(byAddress)
    offset += 70
    const byID = isMsg.slice(offset, offset + 36)
    const byIDhex1 = Buffer.from(byID).toString('hex')
    const byIDhex = this.hexToStr(byIDhex1)
    offset += 36
    const byCompany = isMsg.slice(offset, offset + 30)

    const byCompanyhex = this.byte2Chinese(byCompany)
    offset += 30
    const byBeginDate = isMsg.slice(offset, offset + 16)
    const byBeginDatehex1 = Buffer.from(byBeginDate).toString('hex')
    const byBeginDatehex = this.hexToStr(byBeginDatehex1)
    offset += 16
    const byEndDateDate = isMsg.slice(offset, offset + 16)
    const byEndDatehex1 = Buffer.from(byEndDateDate).toString('hex')
    const byEndDatehex = this.hexToStr(byEndDatehex1)
    return {
      name: byNamehex,
      sex: bySexhex,
      race: byRacehex,
      birth: byBirthhex,
      address: byAddresshex,
      id: byIDhex,
      company: byCompanyhex,
      beginDate: byBeginDatehex,
      endDate: byEndDatehex
    }


  }
  writeFace() {
    const array = new Uint8Array(this.payload)
    const dataView = new DataView(array.buffer)
    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)
    offset += 1
    const totalRecord = dataView.getUint8(offset)
    offset += 1
    const currRecord = dataView.getUint8(offset)
    offset += 1
    const completeFlag = dataView.getUint8(offset)
    return {
      cmd: cmd,
      status: status,
      totalRecord: totalRecord,
      currRecord: currRecord,
      completeFlag: completeFlag,

    }
  }
  readFace() {
    const array = new Uint8Array(this.payload)
    const dataView = new DataView(array.buffer)
    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)

    offset += 1
    const fModeLen = dataView.getUint16(offset)
    offset += 2
    var mode = array.slice(offset, fModeLen + offset)
    const hex = Buffer.from(mode).toString('hex')
    return {
      cmd: cmd,
      status: status,
      fModeLen: fModeLen,
      mode: hex,

    }

  }
  readRFCard() {
    const array = new Uint8Array(this.payload)
    const dataView = new DataView(array.buffer)
    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)
    offset += 1
    if (status === 0) {
      if (array.length > 8) {
        const cardNo = array.slice(offset,offset+8)
        const cardNoHex = Buffer.from(cardNo).toString('hex')
        offset += 8
        const cardType = dataView.getUint8(offset)
        return { cmd: cmd, status: status, cardNo: cardNoHex, cardType: cardType }
      } else {
        const cardNo = dataView.getUint32(offset)
        offset += 4
        const cardType = dataView.getUint8(offset)
        return { cmd: cmd, status: status, cardNo: cardNo.toString(16), cardType: cardType }
      }

    } else {
      return { cmd: cmd, status: status }
    }
  }

  writeRFCard() {
    const array = new Uint8Array(this.payload)
    const dataView = new DataView(array.buffer)
    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)
    return { cmd: cmd, status: status }
  }

  writeFingerPrint() {
    const array = new Uint8Array(this.payload)
    const dataView = new DataView(array.buffer)
    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)

    offset += 1
    const totalRecord = dataView.getUint8(offset)
    offset += 1
    const currRecord = dataView.getUint8(offset)
    offset += 1
    const completeFlag = dataView.getUint8(offset)
    offset += 1
    const fingerprintNo = dataView.getUint16(offset)

    return {
      cmd: cmd,
      status: status,
      totalRecord: totalRecord,
      currRecord: currRecord,
      completeFlag: completeFlag,
      fingerprintNo: fingerprintNo
    }
  }

  readFingerPrint() {
    const array = new Uint8Array(this.payload)
    Logger.info('array' + array)
    const dataView = new DataView(array.buffer)

    let offset = 0
    const cmd = dataView.getUint16(offset)
    offset += 2
    const status = dataView.getUint8(offset)
    offset += 1
    const fpModeLen = dataView.getUint16(offset)
    offset += 2
    var mode = array.slice(offset, fpModeLen + offset)

    const hex = Buffer.from(mode).toString('hex')

    Logger.info('hex' + hex)

    return {
      cmd: cmd,
      status: status,
      fpModeLen: fpModeLen,
      mode: mode,

    }
  }
}

export default class Payload {
  static request(cmd, payload) {
    const request = new Request(cmd, payload)
    switch (cmd) {
      case 0x8010:
        Logger.info('start request 0x8010')
        return request.readRFCard()
      case 0x8011:
        Logger.info('start request 0x8011')
        return request.writeRFCard()
      case 0x8013:
        Logger.info('start request 0x8013')
        return request.writeFingerPrint()
      case 0x8014:
        Logger.info('start request 0x8014')
        return request.readFingerPrint()
      case 0x8016:
        Logger.info('start request 0x8016')
        return request.writeFace()
      case 0x8017:
        Logger.info('start request 0x8017')
        return request.readFace()
      case 0x8018:
        Logger.info('start request 0x8018')
        return request.readIDMessage()
      default:
        return null
    }
  }

  static response(payload) {
    Logger.info('receive payload:' + Utils.byte2HexStr(payload))
    const cmd = (payload[0] << 8) | (payload[1] & 0xff)
    Logger.info('cmd:' + cmd.toString(16))
    const response = new Response(payload)
    switch (cmd) {
      case 0x8010:
        return response.readRFCard()
      case 0x8011:
        return response.writeRFCard()
      case 0x8013:
        return response.writeFingerPrint()
      case 0x8014:
        return response.readFingerPrint()
      case 0x8016:
        return response.writeFace()
      case 0x8017:
        return response.readFace()
      case 0x8018:
        return response.readIDMessage()
      default:

        return 0x80ff
    }
  }
}
