import Utils from './util'
import SM4 from './sm4'
import Logger from './logger'

export default class Packet {
  constructor(obj = {}) {
    this.head = 0xef01ee02
    this.type = obj.type ? obj.type : 0x01
    this.mid = obj.mid ? obj.mid : 0x0001
    this.tag = obj.tag ? obj.tag : 0x00
    // 4个字节
    this.remainLength = 0
    this.payload = []
  }

  /**
     * 只传加密类型
     * 0明文
     * 1ase128
     * 2约定密钥通信
     * 3通信密钥通信
     *
     * @param tag
     ?*/
  setTag(tag) {
    this.tag = tag
  }

  toBytes(payload) {
    this.payload = payload
   
    Logger.info('packet toBytes ' + this.payload.length)
    
    // 明文数据长度
    const plainLen = this.payload.length
    // 加密后数据长度
    let cipherLen = plainLen
    // 加密方式
    const cipher = this.tag & 0x0f
    Logger.info('cipher ' + cipher)
    if (cipher === 1) {
      // aes加密
    } else if (cipher === 2) {
      // 约定密钥通信(lockId)
      const encData = SM4.sm4_enc(this.payload, plainLen, Utils.str2bytes(this.agreeKey))
      this.payload = encData
      cipherLen = this.payload.length
    } else if (cipher === 3) {
      // 通信密钥通信
      const encData = SM4.sm4_enc(this.payload, plainLen, Utils.hexStr2Byte(this.commKey))
      this.payload = encData
      cipherLen = this.payload.length
    }
    this.remainLength = (cipherLen << 16) | plainLen
    const buffer = new ArrayBuffer(12 + cipherLen)
    const dataView = new DataView(buffer)
    let offset = 0
    dataView.setUint32(offset, this.head)
    offset += 4
    dataView.setUint8(offset, this.type)
    offset += 1
    dataView.setUint16(offset, this.mid)
    offset += 2
    dataView.setUint8(offset, this.tag)
    offset += 1
    dataView.setUint32(offset, this.remainLength)
    offset += 4
    for (let i = 0; i < cipherLen; i++) {
      dataView.setUint8(offset, this.payload[i])
      offset += 1
    }
    return new Uint8Array(buffer)
  }

  fromBytes(data) {
    const array = new Uint8Array(data)
    const dataView = new DataView(array.buffer)
    let offset = 0
    this.head = dataView.getUint32(offset)
    offset += 4
    this.type = dataView.getUint8(offset)
    offset += 1
    this.mid = dataView.getUint16(offset)
    offset += 2
    this.tag = dataView.getUint8(offset)
    offset += 1
    this.remainLength = dataView.getUint32(offset)
    offset += 4
    const cipherLen = (this.remainLength >> 16) & 0xffff
    Logger.info('cipherLen:' + cipherLen)
    this.payload = array.subarray(offset, offset + cipherLen)
    const cipher = this.tag & 0x0f
    Logger.info('cipher:' + cipher)
    if (cipher === 1) {
      // aes解密
    } else if (cipher === 2) {
      // 约定密钥解密
      Logger.info('this.key:' + this.agreeKey)
      const decData = SM4.sm4_dec(this.payload, cipherLen, Utils.str2bytes(this.agreeKey))
      this.payload = decData
    } else if (cipher === 3) {
      // 通信密钥解密
      const decData = SM4.sm4_dec(this.payload, cipherLen, Utils.hexStr2Byte(this.commKey))
      this.payload = decData
    }
    return this.payload
  }
}
