<template>
  <view>
    <!-- <customRequestPermission
      ref="requestPer"
      :permissionInfo="permissionInfo"
    ></customRequestPermission> -->
    <view
      class="record-btn"
      @longpress="startRecord"
      @touchstart="touchStart"
      @touchmove="touchMove"
      @touchend="endRecord"
      hover-class="record-btn-hover"
      hover-start-time="200"
      hover-stay-time="150"
      :style="[
        { ...btnStyle, height: chatInputHeight },
        {
          '--btn-hover-fontcolor': btnHoverFontcolor,
          '--btn-hover-bgcolor': btnHoverBgcolor,
        },
      ]"
    >
      <wd-loading
        v-if="isCheckingPermission"
        color="#46299D"
        :size="20"
        style="margin: 0 12rpx 0 0;"
      />
      <text>
        {{
          isCheckingPermission
            ? $t('chat_getting_microphone_permission')
            : btnTextContent
        }}
      </text>
    </view>
    <!-- <view class="record-popup"
			:style="{ '--popup-height': popupHeight, '--popup-width': upx2px(popupMaxWidth), '--popup-bottom': upx2px(popupFixBottom), '--popup-bg-color': popupBgColor }">
			<view class="inner-content" v-if="recordPopupShow">
				<view class="title">{{ popupTitle }}</view>
				<view class="voice-line-wrap" v-if="recording"
					:style="{ '--line-height': upx2px(lineHeight), '--line-start-color': lineStartColor, '--line-end-color': lineEndColor }">
					<view class="voice-line one"></view>
					<view class="voice-line two"></view>
					<view class="voice-line three"></view>
					<view class="voice-line four"></view>
					<view class="voice-line five"></view>
					<view class="voice-line six"></view>
					<view class="voice-line seven"></view>
					<view class="voice-line six"></view>
					<view class="voice-line five"></view>
					<view class="voice-line four"></view>
					<view class="voice-line three"></view>
					<view class="voice-line two"></view>
					<view class="voice-line one"></view>
				</view>
				<view class="cancel-icon" v-if="!recording">+</view>
				<view class="tips">{{ recording ? popupDefaultTips : popupCancelTips }}</view>
			</view>
		</view> -->
    <view class="record-shadow" v-if="recordPopupShow">
      <view
        class="record-animation-area"
        :style="
          recording
            ? ''
            : 'background-image: url(' + recordAnimationAreaCancelBg + ')'
        "
      >
        <view
          class="voice-line-wrap"
          v-if="!nearTimeLimit"
          :style="{
            '--line-height': upx2px(lineHeight),
            '--line-start-color': lineStartColor,
            '--line-end-color': lineEndColor,
          }"
        >
          <view class="voice-line seven"></view>
          <view class="voice-line six"></view>
          <view class="voice-line five"></view>
          <view class="voice-line four"></view>
          <view class="voice-line three"></view>
          <view class="voice-line two"></view>
          <view class="voice-line one"></view>
          <view class="voice-line two"></view>
          <view class="voice-line three"></view>
          <view class="voice-line four"></view>
          <view class="voice-line five"></view>
          <view class="voice-line six"></view>
          <view class="voice-line seven"></view>
          <view class="voice-line six"></view>
          <view class="voice-line five"></view>
          <view class="voice-line four"></view>
          <view class="voice-line three"></view>
          <view class="voice-line two"></view>
          <view class="voice-line one"></view>
          <view class="voice-line two"></view>
          <view class="voice-line three"></view>
          <view class="voice-line four"></view>
          <view class="voice-line five"></view>
          <view class="voice-line six"></view>
          <view class="voice-line seven"></view>
        </view>
        <view class="record-auto-stop-hint" v-if="nearTimeLimit">
          <text>{{ autoStopRecordCountDown + $t('auto_stop_record') }}</text>
        </view>
      </view>
      <view class="record-cancel-btn">
        <image
          v-if="recording"
          src="@/static/image/record/chat-voice-cancel-grey.png"
        ></image>
        <image
          v-if="!recording"
          src="@/static/image/record/chat-voice-cancel-blue.png"
        ></image>
        <text v-if="recording" class="font-36 font-regular"></text>
        <text
          v-if="!recording"
          class="font-36 font-regular"
          style="margin: 20rpx 0 0;"
        >
          {{ $t('release_hand_to_cancel') }}
        </text>
      </view>
      <view
        class="record-shadow-bottom"
        :style="recording ? '' : 'background-color:#fff;'"
      >
        <image
          v-if="recording"
          src="@/static/image/record/chat-voice-icon-white.png"
        ></image>
        <image
          v-if="!recording"
          src="@/static/image/record/chat-voice-icon-blue.png"
        ></image>
        <text class="font-36 font-regular">
          {{ $t('release_hand_to_send') }}
        </text>
      </view>
    </view>
  </view>
</template>
<script>
var that
// #ifdef APP-PLUS
const recorderManager = uni.getRecorderManager()
// 引入权限判断
import permision from '../../js_sdk/wa-permission/permission.js'
// #endif
// #ifdef H5
import Recorder from 'recorder-core'
import RecordApp from 'recorder-core/src/app-support/app'
import '@/uni_modules/Recorder-UniCore/app-uni-support.js'
import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine'
import 'recorder-core/src/extensions/waveview'
import recordCancelBg from '@/static/image/record/chat-voice-animation-bg-red.png'
// #endif
import { multiplication, handleFindWebview } from '@/utils/common'
export default {
  name: 'nbVoiceRecord',
  /**
   * 录音交互动效组件
   * @property {Object} recordOptions 录音配置
   * @property {Object} btnStyle 按钮样式
   * @property {Object} btnHoverFontcolor 按钮长按时字体颜色
   * @property {String} btnHoverBgcolor 按钮长按时背景颜色
   * @property {String} btnDefaultText 按钮初始文字
   * @property {String} btnRecordingText 录制时按钮文字
   * @property {Boolean} vibrate 弹窗时是否震动
   * @property {String} popupTitle 弹窗顶部文字
   * @property {String} popupDefaultTips 录制时弹窗底部提示
   * @property {String} popupCancelTips 滑动取消时弹窗底部提示
   * @property {String} popupMaxWidth 弹窗展开后宽度
   * @property {String} popupMaxHeight 弹窗展开后高度
   * @property {String} popupFixBottom 弹窗展开后距底部高度
   * @property {String} popupBgColor 弹窗背景颜色
   * @property {String} lineHeight 声波高度
   * @property {String} lineStartColor 声波波谷时颜色色值
   * @property {String} lineEndColor 声波波峰时颜色色值
   * @event {Function} startRecord 开始录音回调
   * @event {Function} endRecord 结束录音回调
   * @event {Function} cancelRecord 滑动取消录音回调
   * @event {Function} stopRecord 主动停止录音
   */
  props: {
    recordOptions: {
      type: Object,
      default() {
        return {
          duration: 60000,
        } // 请自行查看各端的的支持情况，这里全部使用默认配置
      },
    },
    chatInputHeight: {
      type: String,
      default: '32px', // 单位为px
    },
    btnStyle: {
      type: Object,
      default() {
        return {
          width: 'calc(100% - 26rpx)',
          height: '32px', // 使用默认值
          borderRadius: '8rpx',
          backgroundColor: '#F9F9F9',
          border: '1rpx solid whitesmoke',
          permisionState: false,
          margin: '0 10rpx 0 16rpx',
          // boxShadow: '0rpx 6rpx 12rpx 2rpx rgba(0, 0, 0, 0.08)',
        }
      },
    },
    btnHoverFontcolor: {
      type: String,
      default: '#000', // 颜色名称或16进制色值
    },
    btnHoverBgcolor: {
      type: String,
      default: 'whitesmoke', // 颜色名称或16进制色值
    },
    btnDefaultText: {
      type: String,
      default: '长按开始录音',
    },
    btnRecordingText: {
      type: String,
      default: '录音中',
    },
    vibrate: {
      type: Boolean,
      default: true,
    },
    popupTitle: {
      type: String,
      default: '正在录制音频',
    },
    popupDefaultTips: {
      type: String,
      default: '左右滑动后松手完成录音',
    },
    popupCancelTips: {
      type: String,
      default: '松手取消录音',
    },
    popupMaxWidth: {
      type: Number,
      default: 600, // 单位为rpx
    },
    popupMaxHeight: {
      type: Number,
      default: 300, // 单位为rpx
    },
    popupFixBottom: {
      type: Number,
      default: 200, // 单位为rpx
    },
    popupBgColor: {
      type: String,
      default: 'whitesmoke',
    },
    lineHeight: {
      type: Number,
      default: 50, // 单位为rpx
    },
    lineStartColor: {
      type: String,
      default: 'royalblue', // 颜色名称或16进制色值
    },
    lineEndColor: {
      type: String,
      default: 'indianred', // 颜色名称或16进制色值
    },
    field: {
      type: String,
      default: 'voiceRecord',
    },
  },
  data() {
    return {
      stopStatus: false, // 是否已被父页面通知主动结束录音
      btnTextContent: this.btnDefaultText,
      startTouchData: {},
      popupHeight: '0px', // 这是初始的高度
      recording: true, // 录音中
      recordPopupShow: false, //是否显示录音弹窗
      recordTimeout: null, // 录音定时器
      recordAnimationAreaCancelBg: recordCancelBg, //录音动画区域取消时背景
      permissionInfo: '', //当前请求的权限
      nearTimeLimit: false, //是否录音将超时
      autoStopRecordCountDown: 0, //自动停止录音倒计时
      autoStopRecordInterval: null, //自动停止录音技术定时器
      permisionState: false, //权限授权状态
      isCheckingPermission: true, //是否正在获取权限
    }
  },
  mounted() {
    let that = this
    that.isMounted = true
    RecordApp.UniRenderjsRegister(that)
    window.handleAppMicro = that.handleAppMicro
    // that.$store.dispatch('updateCurrentComponentRef', that)
  },
  onShow() {
    let that = this
    if (that.isMounted) RecordApp.UniPageOnShow(that)
  },
  created() {
    let that = this

    // 请求权限
    that.checkPermission()

    // #ifdef APP-PLUS
    recorderManager.onStop((res) => {
      // 判断是否用户主动结束录音
      if (that.recordTimeout !== null) {
        // 延时未结束，则是主动结束录音
        clearTimeout(that.recordTimeout)
        that.recordTimeout = null // 恢复状态
      }

      // 继续判断是否为取消录音
      if (that.recording) {
        that.$emit('endRecord', res)
      } else {
        // 用户向上滑动，此时松手后响应的是取消录音的回调
        that.recording = true // 恢复状态
        that.$emit('cancelRecord')
      }
      if (that.autoStopRecordInterval) {
        clearInterval(that.autoStopRecordInterval)
        that.autoStopRecordInterval = null
      }
    })

    recorderManager.onError((err) => {
      console.log('err:', err)
    })
    // #endif
  },
  computed: {},
  methods: {
    upx2px(upx) {
      return uni.upx2px(upx) + 'px'
    },
    handleAppMicro(permissionStatus) {
      let that = this
      // setTimeout(function () {
      //   that.$refs.requestPer.hideCustomPermission()
      // }, 1000)
      if (Number(permissionStatus) === 1) {
        that.continueAppMicro()
      } else if (
        Number(permissionStatus) === -1 ||
        (Number(permissionStatus) === 0 &&
          uni.getSystemInfoSync().osName === 'ios')
      ) {
        uni.showModal({
          title: '提示',
          content: '检测到您还未授权麦克风哦',
          showCancel: true,
          confirmText: '去授权',
          cancelText: '保持拒绝',
          success: ({ confirm, cancel }) => {
            if (confirm) {
              handleFindWebview(`handleRequestAndroidPermission('settings')`)
            }
            if (cancel) {
              that.isCheckingPermission = false
            }
          },
        })
      }
    },
    handleRequestPer(permissionInfo, permissionID) {
      console.log(permissionInfo)
      let that = this
      if (permissionInfo == 'closePermissionRequest') {
        that.permissionInfo = ''
        that.$refs.requestPer.hideCustomPermission()
      } else if (permissionInfo == 'showPermissionRefuseModal') {
        that.$refs.requestPer.showupCustomPermission()
        that.permissionInfo = permissionID
        console.log('权限被拒绝：' + permissionID)
        that.$refs.requestPer.showupPopupPrompt()
      } else {
        that.$refs.requestPer.showupCustomPermission()
        that.permissionInfo = permissionInfo
      }
    },
    continueAppMicro() {
      let that = this
      RecordApp.UniWebViewActivate(that) //App环境下必须先切换成当前页面WebView
      RecordApp.RequestPermission(
        () => {
          console.log('已获得录音权限，可以开始录音了')
          that.permisionState = true
          that.isCheckingPermission = false
          setTimeout(() => {
            if (!that.recordPopupShow) {
              that.stopRecord()
            }
          }, 2000)
        },
        (msg, isUserNotAllow) => {
          that.isCheckingPermission = false
          if (isUserNotAllow) {
            //用户拒绝了录音权限
            //这里你应当编写代码进行引导用户给录音权限，不同平台分别进行编写
          }
          console.error('请求录音权限失败：' + msg)
        },
      )
    },
    async checkPermission() {
      let that = this
      // #ifdef APP-PLUS
      // 先判断os
      let os = uni.getSystemInfoSync().osName
      if (os == 'ios') {
        that.permisionState = await permision.judgeIosPermission('record')
      } else {
        that.permisionState = await permision.requestAndroidPermission(
          'android.permission.RECORD_AUDIO',
        )
      }
      if (that.permisionState !== true && that.permisionState !== 1) {
        uni.showToast({
          title: '请先授权使用录音',
          icon: 'none',
        })
        return
      }
      // #endif

      // #ifndef APP-PLUS
      // #ifndef H5
      uni.authorize({
        scope: 'scope.record',
        success: () => {
          that.permisionState = true
        },
        fail() {
          uni.showToast({
            title: '请授权使用录音',
            icon: 'none',
          })
        },
      })
      // #endif
      // #ifdef H5
      if (typeof plus !== 'undefined') {
        handleFindWebview(`handleRequestAndroidPermission('micro')`)
      } else {
        that.continueAppMicro()
      }
      // #endif
      // #endif
    },

    startRecord() {
      let that = this
      if (!that.permisionState) {
        that.checkPermission()
        return
      }
      that.stopStatus = false
      setTimeout(() => {
        that.popupHeight = that.upx2px(that.popupMaxHeight)
        setTimeout(() => {
          that.recordPopupShow = true
          that.btnTextContent = that.btnRecordingText
          if (that.vibrate) {
            // #ifdef APP-PLUS
            plus.device.vibrate(35)
            // #endif
            // #ifdef MP-WEIXIN
            uni.vibrateShort()
            // #endif
          }
          // 开始录音
          // #ifdef APP-PLUS
          recorderManager.start(that.recordOptions)
          // #endif
          // #ifndef APP-PLUS
          // #ifdef H5
          //录音配置信息
          var set = {
            type: 'mp3',
            sampleRate: 16000,
            bitRate: 16,
            onProcess: (
              buffers,
              powerLevel,
              duration,
              sampleRate,
              newBufferIdx,
              asyncEnd,
            ) => {
              // #ifdef H5 || MP-WEIXIN
              if (that.waveView)
                that.waveView.input(
                  buffers[buffers.length - 1],
                  powerLevel,
                  sampleRate,
                )
              // #endif
              if (that.clearBufferIdx > newBufferIdx) {
                that.clearBufferIdx = 0
              } //重新录音了就重置
              for (var i = that.clearBufferIdx || 0; i < newBufferIdx; i++)
                buffers[i] = null
              that.clearBufferIdx = newBufferIdx
            },
          }
          RecordApp.UniWebViewActivate(that) //App环境下必须先切换成当前页面WebView
          RecordApp.Start(
            set,
            () => {
              console.log('已开始录音')
            },
            (msg) => {
              console.error('开始录音失败：' + msg)
            },
          )
          // #endif
          // #endif

          that.nearTimeLimit = false
          // 设置定时器
          that.recordTimeout = setTimeout(
            () => {
              // 如果定时器先结束，则说明此时录音时间超限
              that.stopRecord() // 结束录音动画（实际上录音的end回调已经先执行）
              that.recordTimeout = null // 重置
            },
            that.recordOptions.duration ? that.recordOptions.duration : 600000,
          )

          that.autoStopRecordCountDown = 11
          let count = 0
          that.autoStopRecordInterval = setInterval(() => {
            count += 1000
            if (
              count >=
              that.recordOptions.duration -
                multiplication(that.autoStopRecordCountDown, 1000)
            ) {
              that.nearTimeLimit = true
              that.autoStopRecordCountDown--
              if (that.autoStopRecordCountDown <= 0) {
                clearInterval(that.autoStopRecordInterval)
                that.autoStopRecordInterval = null
              }
            }
          }, 1000)

          that.$emit('startRecord')
        }, 100)
      }, 200)
    },
    endRecord() {
      let that = this
      if (that.stopStatus) {
        return
      }
      that.popupHeight = '0px'
      that.recordPopupShow = false
      that.btnTextContent = that.btnDefaultText
      // #ifdef APP-PLUS
      recorderManager.stop()
      // #endif
      // #ifndef APP-PLUS
      // #ifdef H5
      RecordApp.Stop(
        (arrayBuffer, duration, mime) => {
          var blob = new Blob([arrayBuffer], {
            type: mime,
          })
          let url = (window.URL || webkitURL).createObjectURL(blob)
          console.log(blob, url)
          var file = new File([arrayBuffer], 'recorder.mp3')
          // 判断是否用户主动结束录音
          if (that.recordTimeout !== null) {
            // 延时未结束，则是主动结束录音
            clearTimeout(that.recordTimeout)
            that.recordTimeout = null // 恢复状态
          }
          // 继续判断是否为取消录音
          if (that.recording) {
            // console.log(file)
            that.$emit('endRecord', file, url, duration)
            ;(window.URL || webkitURL).revokeObjectURL(url)
          } else {
            // 用户向上滑动，此时松手后响应的是取消录音的回调
            that.recording = true // 恢复状态
            that.$emit('cancelRecord')
          }
          if (that.autoStopRecordInterval) {
            clearInterval(that.autoStopRecordInterval)
            that.autoStopRecordInterval = null
          }
        },
        (msg) => {
          console.error('结束录音失败：' + msg)
        },
      )
      // #endif
      // #endif
    },
    stopRecord() {
      let that = this
      // 用法如你录音限制了时间，那么将在结束时强制停止组件的显示
      that.endRecord()
      that.stopStatus = true
    },
    touchStart(e) {
      let that = this
      that.startTouchData.clientX = e.changedTouches[0].clientX //手指按下时的X坐标
      that.startTouchData.clientY = e.changedTouches[0].clientY //手指按下时的Y坐标
    },
    touchMove(e) {
      let that = this
      let touchData = e.touches[0] //滑动过程中，手指滑动的坐标信息 返回的是Objcet对象
      let moveX = touchData.clientX - that.startTouchData.clientX
      let moveY = touchData.clientY - that.startTouchData.clientY
      if (moveY < -130) {
        if (that.vibrate && that.recording) {
          // #ifdef APP-PLUS
          plus.device.vibrate(35)
          // #endif
          // #ifdef MP-WEIXIN
          uni.vibrateShort()
          // #endif
        }
        that.recording = false
      } else {
        that.recording = true
      }
    },
  },
}
</script>
<style lang="scss">
.record-btn {
  color: #000;
  font-size: 24rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: 0.25s all;
  border: 1rpx solid whitesmoke;
  font-size: 36rpx;
  font-weight: 500;
  color: #1a1a1a;
  box-sizing: border-box;
  text {
    font-size: 30rpx;
    font-weight: 600;
    line-height: 1;
  }
}

.record-btn-hover {
  color: var(--btn-hover-fontcolor) !important;
  background-color: var(--btn-hover-bgcolor) !important;
}

.record-popup {
  position: absolute;
  bottom: var(--popup-bottom);
  left: calc(50vw - calc(var(--popup-width) / 2));
  z-index: 1;
  width: var(--popup-width);
  height: var(--popup-height);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10rpx;
  box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
  background: var(--popup-bg-color);
  color: #000;
  transition: 0.2s height;

  .inner-content {
    height: var(--popup-height);
    font-size: 24rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;

    .title {
      font-weight: bold;
      padding: 20rpx 0;
    }

    .tips {
      color: #999;
      padding: 20rpx 0;
    }
  }
}

.cancel-icon {
  width: 100rpx;
  height: 100rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 44rpx;
  line-height: 44rpx;
  background-color: pink;
  border-radius: 50%;
  transform: rotate(45deg);
}

.voice-line-wrap {
  display: flex;
  align-items: center;

  .voice-line {
    width: 5rpx;
    height: var(--line-height);
    border-radius: 3rpx;
    margin: 0 5rpx;
  }

  .one {
    animation: wave 0.4s 1s linear infinite alternate;
  }

  .two {
    animation: wave 0.4s 0.9s linear infinite alternate;
  }

  .three {
    animation: wave 0.4s 0.8s linear infinite alternate;
  }

  .four {
    animation: wave 0.4s 0.7s linear infinite alternate;
  }

  .five {
    animation: wave 0.4s 0.6s linear infinite alternate;
  }

  .six {
    animation: wave 0.4s 0.5s linear infinite alternate;
  }

  .seven {
    animation: wave 0.4s linear infinite alternate;
  }
}

.record-auto-stop-hint {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;

  text {
    color: #fff;
    margin-top: -24rpx;
  }
}

@keyframes wave {
  0% {
    transform: scale(1, 1);
    background-color: var(--line-start-color);
  }

  100% {
    transform: scale(1, 0.2);
    background-color: var(--line-end-color);
  }
}

.record-shadow {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.4);
  z-index: 12;

  .record-animation-area {
    position: absolute;
    bottom: 50%;
    left: 50%;
    width: 468rpx;
    height: 143rpx;
    margin-top: -71.5rpx;
    margin-left: -234rpx;
    background-image: url('@/static/image/record/chat-voice-animation-bg-blue.png');
    background-size: 100% 100%;
    background-repeat: no-repeat;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;

    .voice-line-wrap {
      margin-top: -17rpx;
    }
  }

  .record-cancel-btn {
    position: absolute;
    bottom: 320rpx;
    left: 50%;
    margin-left: -74rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;

    image {
      width: 148rpx;
      height: 148rpx;
    }

    text {
      color: #fff;
      margin: 8rpx;
      height: 48rpx;
      line-height: 1;
      display: inline-block;
    }
  }

  .record-shadow-bottom {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 274rpx;
    background-color: #4686e2;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;

    image {
      width: 44rpx;
      height: 62rpx;
      position: relative;
      z-index: 2;
    }

    text {
      margin: 22rpx 0 0;
      color: #fff;
    }
  }

  .record-shadow-bottom::after {
    content: '';
    position: absolute;
    width: 100%;
    height: 68rpx;
    border-radius: 100%;
    background: inherit;
    bottom: 274rpx;
    left: 50%;
    transform: translate(-50%, 50%);
    z-index: 1;
  }
}
</style>
