<template>
  <div>
    <div class="itemBMaxBox tc">
      <div class="wih100 tc">
        <div v-if="flag">
          <div class="mt24 cf f16 fw700">实时广播</div>
          <div class="cf mt5 f12">{{ time }}</div>
        </div>
        <div v-else>
          <div class="mt24 cf f16 fw700">实时广播</div>
          <div class="cf mt5 f12">{{ time }}</div>
        </div>
      </div>
      <div class="wih100">
        <div class="AudioBG tc mt24 dib">
          <img class="" src="../../assets/images/PagerP1/AudioBG2.png" alt="" />
        </div>
      </div>
      <div v-if="flag" class="bottomBtnBox jcsb mt30 pl24 pr24">
        <div class="cf f14">
          <div class="w35 h35 lh35 tc">
            <div class="w15 h15 ml8 iconfont" />
          </div>
          <div />
        </div>
        <div class="cf f14">
          <div class="w30 h30 lh30 btnStyle tc cp" @click="play">
            <div
              class="w5 h5 ml8 iconfont"
              :class="isPlay ? 'icon-wanchengluyin' : 'icon-kaishiluyin'"
            />
          </div>
          <div>{{ !isPlay ? '开始喊话' : '结束喊话' }}</div>
        </div>
        <div class="cf f14" :class="{ vish: !isPlay }">
          <div class="w35 h35">
            <div class="w5 h5 mt10 ml9 iconfont" />
          </div>
          <div />
        </div>
      </div>
      <!-- <div class="mt40" v-if="!flag">
        <div class="bottomBtnBox mr jcenter">
          <div class="cf f14" @click="change">
            <div class="w45 h45 lh45 btnStyle tc cp">
              <div class="w15 h15 ml13 iconfont icon-moshiqiehuan"></div>
            </div>
            <div>模式切换</div>
          </div>
        </div>
      </div> -->
    </div>
  </div>
</template>

<script>
import CmdStreamFunction from '../utils/cmd_stream_function';
import CmdStreamUpData from '../utils/cmd_stream_up_data';
// 必须引入的核心，换成require也是一样的。注意：recorder-core会自动往window下挂载名称为Recorder对象，全局可调用window.Recorder，也许可自行调整相关源码清除全局污染
import Recorder from 'recorder-core';
// 需要使用到的音频格式编码引擎的js文件统统加载进来
import 'recorder-core/src/engine/mp3';
import 'recorder-core/src/engine/mp3-engine';
import 'recorder-core/src/engine/pcm';
export default {
  data() {
    return {
      flag: true,
      isPlay: false,
      hours: '00',
      time: '00:00:00',
      setIntervalTime: '',
      s: 0,
      h: 0,
      f: 0,
      action: null,
      result: null,
      type: null
    };
  },
  inject: ['PagerP1', 'PoliceKey'],
  watch: {
    action: {
      handler(val) {
        if (val == 12 && this.type == 0 && this.result == 0) {
          this.say();
        }
      }
    }
  },
  mounted() {},
  beforeDestroy() {
    this.handleStartShoutDown();
  },
  methods: {
    reset() {
      clearInterval(this.setIntervalTime);
      this.time = '00:00:00';
      this.s = 0;
      this.h = 0;
      this.f = 0;
      this.isPlay = false;
    },
    change() {
      this.flag = !this.flag;
      this.reset();
      if (!this.flag) {
        this.handleStartShout();
        this.init();
      } else {
        this.handleStartShoutDown();
      }
    },

    play() {
      this.isPlay = !this.isPlay;
      if (!this.isPlay) {
        // 完成录音
        this.handleStartShoutDown();
        this.reset();
      } else {
        // this.init();
        this.init();
        this.handleStartShout();
        this.$emit('playAudio', 14);
      }
    },
    init() {
      this.setIntervalTime = setInterval(() => {
        this.s += 1;
        if (this.s === 60) {
          this.s = 0;
          this.f += 1;
          if (this.f === 60) {
            this.h += 1;
          }
        }
        if (this.s < 10 && this.f < 10) {
          this.time = '0' + this.h + ':' + 0 + this.f + ':' + 0 + this.s;
        } else if (this.s < 10 && this.f >= 10) {
          this.time = '0' + this.h + ':' + this.f + ':' + 0 + this.s;
        } else if (this.s >= 10 && this.f < 10) {
          this.time = '0' + this.h + ':' + 0 + this.f + ':' + this.s;
        } else if (this.s >= 10 && this.f >= 10) {
          this.time = '0' + this.h + ':' + this.f + ':' + this.s;
        }
      }, 1000);
    },
    handleStartShout() {
      // 结束喊话指令
      // let cmd = new CmdStreamFunction(13, 0);
      // let message = cmd.pack();
      // message = Uint8Array.from(message);
      // this.mqtt_publish(message);
      // // 开始喊话指令
      // cmd = new CmdStreamFunction(12, 0);
      // message = cmd.pack();
      // message = Uint8Array.from(message);
      const message = {
        data: 12,
        type: 2317
      };
      this.mqtt_publish(message);
      const _this = this;
    },
    say() {
      const _this = this;
      function sendAllBytes(arrayBuffer) {
        // console.log(arrayBuffer);
        var uint8array = new Uint8Array(arrayBuffer);
        const list = [...uint8array];
        const mav_list = [];
        while (list.length > 0) {
          const byte250 = list.splice(0, 250);
          const uint8array = Uint8Array.from(byte250);
          const array = [...uint8array];
          const cmd = new CmdStreamUpData(array.length, array);
          const message = cmd.pack();
          mav_list.push(...message);
        }
        const message = Uint8Array.from(mav_list);
        const datas = {
          data: Array.from(uint8array),
          type: 2318
        };
        _this.mqtt_publish(datas);
      }

      var testSampleRate = 16000;
      var testBitRate = 16;
      var SendInterval = 1;

      /** ****
          转码发送间隔（实际间隔比这个变量值偏大点，取决于BufferSize）。这个值可以设置很大，但不能设置很低，毕竟转码和传输还是要花费一定时间的，设备性能低下可能还处理不过来。

          mp3格式下一般大于500ms就能保证能够正常转码处理，wav大于100ms，剩下的问题就是传输速度了。由于转码操作都是串行的，录制过程中转码生成出来mp3顺序都是能够得到保证，但结束时最后几段数据可能产生顺序问题，需要留意。由于传输通道不一定稳定，后端接收到的顺序可能错乱，因此可以携带编号进行传输，完成后进行一次排序以纠正顺序错乱的问题。

          mp3格式在间隔太低的情况下中间的停顿会非常明显，可适当调大间隔以规避此影响，因为mp3编码时首尾出现了填充的静默数据（mp3.js编码器内已尽力消除了这些静默，但还是会有些许的静默停顿）；wav格式没有此问题，测试时可以打开 testOutputWavLog + mp3、wav合并demo 来对比音质。

          当出现性能问题时，可能音频编码不过来，将采取丢弃部分帧的策略。
        ******/

      // 重置环境
      var RealTimeSendTryReset = function (type) {
        realTimeSendTryType = type;
        realTimeSendTryTime = 0;
      };

      var realTimeSendTryType;
      var realTimeSendTryEncBusy;
      var realTimeSendTryTime = 0;
      var realTimeSendTryNumber;
      var transferUploadNumberMax;
      var realTimeSendTryChunk;

      // =====实时处理核心函数==========
      var RealTimeSendTry = function (rec, isClose) {
        var t1 = Date.now();
        var endT = 0;
        var recImpl = Recorder.prototype;
        if (realTimeSendTryTime == 0) {
          realTimeSendTryTime = t1;
          realTimeSendTryEncBusy = 0;
          realTimeSendTryNumber = 0;
          transferUploadNumberMax = 0;
          realTimeSendTryChunk = null;
        }
        if (!isClose && t1 - realTimeSendTryTime < SendInterval) {
          return; // 控制缓冲达到指定间隔才进行传输
        }
        realTimeSendTryTime = t1;
        var number = ++realTimeSendTryNumber;

        // 借用SampleData函数进行数据的连续处理，采样率转换是顺带的
        var chunk = Recorder.SampleData(
          rec.buffers,
          rec.srcSampleRate,
          testSampleRate,
          realTimeSendTryChunk,
          { frameType: isClose ? '' : realTimeSendTryType }
        );

        // 清理已处理完的缓冲数据，释放内存以支持长时间录音，最后完成录音时不能调用stop，因为数据已经被清掉了
        for (var i = realTimeSendTryChunk ? realTimeSendTryChunk.index : 0; i < chunk.index; i++) {
          rec.buffers[i] = null;
        }
        realTimeSendTryChunk = chunk; // 此时的chunk.data就是原始的音频pcm数据，直接保存即为pcm文件、加个wav头即为wav文件、丢给mp3编码器转一下码即为mp3文件

        // 实时编码队列阻塞处理
        if (!isClose) {
          if (realTimeSendTryEncBusy >= 2) {
            // console.log("编码队列阻塞，已丢弃一帧");
            return;
          }
        }
        realTimeSendTryEncBusy++;

        // 通过mock方法实时转码成mp3、wav；pcm格式可以不经过此操作，直接发送chunk.data
        var encStartTime = Date.now();
        var recMock = Recorder({
          type: realTimeSendTryType,
          sampleRate: testSampleRate, // 采样率
          bitRate: testBitRate // 比特率
        });
        recMock.mock(chunk.data, chunk.sampleRate);

        recMock.stop(
          function (blob, duration) {
            realTimeSendTryEncBusy && realTimeSendTryEncBusy--;
            blob.encTime = Date.now() - encStartTime;
            sendAllBytes(chunk.data.buffer);
          },
          function (msg) {
            realTimeSendTryEncBusy && realTimeSendTryEncBusy--;
          }
        );
      };

      // 调用录音
      var rec;
      function recStartPcm() {
        recStart('pcm');
      }
      function recStart(type) {
        if (rec) {
          rec.close();
        }
        rec = Recorder({
          type: 'unknown',
          onProcess: function (buffers, powerLevel, bufferDuration, bufferSampleRate) {
            // 推入实时处理，因为是unknown格式，这里简化函数调用，没有用到buffers和bufferSampleRate，因为这些数据和rec.buffers是完全相同的。
            RealTimeSendTry(rec, false);
          }
        });

        var t = setTimeout(function () {}, 8000);

        rec.open(
          function () {
            // 打开麦克风授权获得相关资源
            clearTimeout(t);
            rec.start(); // 开始录音

            RealTimeSendTryReset(type); // 重置
          },
          function (msg, isUserNotAllow) {
            clearTimeout(t);
          }
        );
      }
      function recStop() {
        rec.close(); // 直接close掉即可，这个例子不需要获得最终的音频文件

        RealTimeSendTry(rec, true); // 最后一次发送
      }

      this.recStop = recStop;

      recStartPcm();
    },
    handleStartShoutDown() {
      this.recStop && this.recStop();
      // if(this.action == 13 && this.type == 0 && this.result == 0){
      const message = {
        data: 13,
        type: 2317
      };
      this.mqtt_publish(message);
      // }
    },
    async mqtt_publish(message) {
      if (this.PoliceKey()) {
        const key = await this.PoliceKey();
        this.PagerP1.mqtt.client.publish(
          `SPEAK/OBTAIN/${key}-01`,
          new TextEncoder().encode(JSON.stringify(message)),
          {
            qos: 0
          },
          (e) => {
            console.log('发送指令成功:', message);
          }
        );
        this.PagerP1.mqtt.client.on('message', (topic, payload, packet) => {
          const data = JSON.parse(packet.payload.toString());
          this.action = data.action;
          this.result = data.result;
          this.type = data.type;
          // console.log(this.action,this.result,this.type);
        });
      }
    }
  }
};
</script>

<style lang="scss" scoped>
.itemBMaxBox {
  width: 327px;
  height: 231px;
  border-radius: 2px 2px 0px 0px;
  border: 1px solid #315ec7;
}
.AudioBG {
  // width: 267px;
  // height: 25px;
  padding: 5px 5px;
  border: 1px solid #3263a5;
}
.bottomBtnBox {
  .btnStyle {
    cursor: pointer;
    border-radius: 50%;
    background: #9bacbe;
    color: #3e495b;
    border: 10px solid #000;
    .bf {
      transform: rotate(90deg);
    }
  }
  .btnStyle:hover {
    color: #43deff;
  }
}
.vish {
  visibility: hidden;
}
.jcenter {
  display: flex;
  justify-content: center;
}
</style>
