const StateMachine=require('./state-machine.min.js') 
const jsbuffer=require('./jsbuffer.min.js')
const deepcopy = require('./deepcopy.min.js')
/**
 * 蓝牙接收类解决多数据包 组包和校验的返回完整数据hex
 * iambtr
 * option{
 *  timer:超时时长
 *  protocolHead：头部
 *  protocolType:协议编号  
 * }
 */
class BlueReadBuffer {
  constructor(option) {
    this.checkTimer = null
    this.fsm=null
    this.msgType=null
    this.hexData=''
    this.useData=[]
    this.dataLength=null
    this.checkSum = new Uint8Array(new ArrayBuffer(2))
    this.opt={
      timer:5000,
      protocolHead: 'ffaa',
      protocolType:'fa',
      byteLength:47
    }
    this.init(option)
    return this
  }
  init(option) {
    deepcopy(this.opt,option)
    this.fsm = new StateMachine({
      init: 'HEAD',
      transitions: [
        { name: 'head', from: 'HEAD', to: 'TYPE' },
        { name: 'type', from: 'TYPE', to: 'DATA' },
        { name: 'data', from: 'DATA', to: 'CHECK' },
        { name: 'ckeck', from: ['HEAD', 'TYPE', 'DATA', 'CHECK', 'DATA', 'END'], to: 'HEAD' }
      ]
    });
  }
  reduceProcess(buff, successCallBack, failCallBack) {
    //检查超时
    this.check_timer(failCallBack);

    let jsbuff=new jsbuffer().read(buff)
    this.hexData+=jsbuff.hex
    for (var i = 0; i < jsbuff.uint8array.length; i++) {
      var chr = jsbuff.get[i];
      switch (this.fsm.state) {
        case 'HEAD':
          if (chr == Number(`${this.opt.protocolHead}.slice(0,2)`)) {
            this.useData.push(chr)
            break
          }
          if ((chr == Number(`${this.opt.protocolHead}.slice(2)`))&&this.useData.length!=0) {
            this.useData.push(chr)
            this.fsm.head();
            break
          }
          this.clear()
          break
        case 'TYPE':
          if (this.useData.length==2) {
            this.useData.push(chr)
            break
          }
          else if(this.useData.length==3) {
            this.useData.push(chr)
            this.dataLength=chr
            this.fsm.type()
            break
          }
            this.clear()
            break
        case 'DATA':
          if (this.useData.length < this.dataLength+4){
            this.useData.push(chr)
            if (this.useData.length == this.dataLngth + 4) {
              this.fsm.data()
            }
            break
          }
          this.clear()
          break
        case 'CHECK':
          if (this.useData.length < this.opt.byteLength) {
            this.useData.push(chr)
            if (this.useData.length == this.opt.byteLength) {
              this.checkSum[0] = this.useData.pop()
              this.checkSum[1] = this.useData.pop()
              let cSum = new Uint16Array(this.checkSum.buffer)
              let sum=this.useData.reduce((pre,cur)=>{
                return pre + cur
              })
              if (cSum == sum) {
                successCallBack && successCallBack(this.useData, this.hexData);
              } else {
                failCallBack && failCallBack('校验位不对')
              }
              this.clear()
            }
          }
          break
        case 'END':
          if (this.use_data_cnt < this.use_data_len) {
            this.use_data[this.use_data_cnt + 4] = chr;
            this.use_data_cnt++;
          }
          if (this.use_data_cnt == this.use_data_len) {
            this.fsm.sum1();
          }
          break;
      }
    }
  }


  clear() {
    this.fsm.check()
    clearTimeout(this.checkTimer)
    this.useData = []
    this.msgType = null
    this.hexData = ''
    this.dataLength = null
    this.checkSum = new ArrayBuffer(2)
  }

  check_timer(failCallBack) {
    clearTimeout(this.checkTimer)
    this.checkTimer = setTimeout(() => {
      this.clear();
      failCallBack && failCallBack('帧解析数据超时')
    }, this.opt.timer)
  }
}
module.exports = BlueReadBuffer