/*
 * @Author: 吴文洁
 * @Date: 2020-03-18 10:01:28
 * @LastEditors: yuananting
 * @LastEditTime: 2021-06-09 14:44:01
 * @Description: 录音组件
 */

import React, { Component } from "react";
import { Button, Modal } from "antd";

import UploadOss from "@/core/upload";
import { RECORD_ERROR } from "@/common/constants/academic";
import AudioRecorder from "../components/audioRecord";
import Platform from '@/core/platform';
import WechatApi from "@/common/js/wechatApi";

import "./XMRecord.less";

class XMRecord extends Component {
  constructor(props) {
    super(props);
    //从麦克风获取的音频流
    this.mAudioContext = null;
    this.mAudioFromMicrophone = null;
    this.mMediaRecorder = null;
    this.mChunks = [];

    this.state = {
      isFinished: true,
      recordTime: 0,
    };
  }

  componentDidMount() {
    // 获取录音设备
    this.getAudioRecorderDevice();
  }

  componentWillUnmount() {}

  getAudioRecorderDevice = () => {
    //仅用来进行录音
    const constraints = { audio: true };
    // 老的浏览器可能根本没有实现 mediaDevices，所以我们可以先设置一个空的对象
    if (navigator.mediaDevices === undefined) {
      navigator.mediaDevices = {};
    }
    // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia
    // 因为这样可能会覆盖已有的属性。这里我们只会在没有getUserMedia属性的时候添加它。
    if (navigator.mediaDevices.getUserMedia === undefined) {
      navigator.mediaDevices.getUserMedia = function (constraints) {
        // 首先，如果有getUserMedia的话，就获得它
        var getUserMedia =
          navigator.getUserMedia ||
          navigator.webkitGetUserMedia ||
          navigator.mozGetUserMedia;
        // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口
        if (!getUserMedia) {
          return Promise.reject(
            new Error("getUserMedia is not implemented in this browser")
          );
        }

        // 否则，为老的navigator.getUserMedia方法包裹一个Promise
        return new Promise(function (resolve, reject) {
          getUserMedia.call(navigator, constraints, resolve, reject);
        });
      };
    }
  };

  openDeviceFailure = (reason) => {
    const { title = "麦克风调用错误", content = "请检查麦克风是否可用" } =
      RECORD_ERROR[reason.name] || {};
    Modal.info({
      title,
      content,
      okText: "我知道了",
    });
  };

  handleCloseConfirm = () => {
    this.$confirm = null;
    this.forceUpdate();
  };

  handleStartRecord = () => {
    if(Platform.isWorkWx()) { // 企业微信
      WechatApi.startRecord();
    }
    navigator.mediaDevices
    .getUserMedia({
      audio: true,
    })
    .then((stream) => {
      this.mMediaRecorder = new AudioRecorder(stream);
      this.mMediaRecorder.start();
      this.handleCountTime();
    }, this.openDeviceFailure);
  };

  onProcessData = (audioData) => {
    this.mChunks.push(audioData.data);
  };

  handleCountTime = () => {
    const { maxTime = 180 } = this.props;
    this.setState({ isFinished: false });

    // 开始计时
    this.timer = window.setInterval(() => {
      const { recordTime } = this.state;
      if (recordTime > maxTime - 1) {
        window.clearInterval(this.timer);
        this.handleFinishRecord();
        return;
      }
      this.setState({
        recordTime: this.state.recordTime + 1,
      });
    }, 1000);
  };

  handleFinishRecord = () => {
    if (this.mMediaRecorder) {
      this.mMediaRecorder.stop();
    }
    const blob = this.mMediaRecorder.upload();
    UploadOss.uploadBlobToOSS(blob, window.random_string(16) + ".wav").then(
      (mp3URL) => {
        const { recordTime } = this.state;
        this.props.onFinish(mp3URL, recordTime * 1000);
        this.setState({
          recordTime: 0,
          isFinished: true,
        });
        window.clearInterval(this.timer);
      }
    );
  };

  // 格式化当前录音时长
  formatRecordTime = (timeStamp) => {
    let minutes = Math.floor(timeStamp / 60);
    let seconds = timeStamp % 60;

    minutes = minutes < 10 ? `0${minutes}` : minutes;
    seconds = seconds < 10 ? `0${seconds}` : seconds;

    return `${minutes}:${seconds}`;
  };

  handleCancel = () => {
    if (this.mMediaRecorder) {
      this.mMediaRecorder.stop();
    }
    window.clearInterval(this.timer);
    this.setState(
      {
        recordTime: 0,
        isFinished: true,
      },
      () => {
        this.props.onCancel();
      }
    );
  };

  render() {
    const { isFinished, recordTime } = this.state;
    const { visible, maxTime = 180 } = this.props;
    return (
      <div className={`xm-record ${visible ? "visible" : "hidden"}`}>
        <div className="record-left">
          <div className="text">
            {isFinished ? (
              <img
                style={{ width: 14, height: 14 }}
                src="https://image.xiaomaiketang.com/xm/xCahGm2Q2J.png"
              />
            ) : (
              <img src="https://xiaomai-image.oss-cn-hangzhou.aliyuncs.com/1584607726775.png" />
            )}
            {isFinished ? <span>录音</span> : <span>录音中...</span>}
          </div>
          <div className="time">{`${this.formatRecordTime(
            recordTime
          )}/${this.formatRecordTime(maxTime)}`}</div>
        </div>

        <div className="btn-wrapper">
          <Button onClick={this.handleCancel}>取消</Button>
          {isFinished ? (
            <Button type="primary" onClick={this.handleStartRecord}>
              开始
            </Button>
          ) : (
            <Button
              type="primary"
              className="finish"
              onClick={this.handleFinishRecord}
            >
              完成
            </Button>
          )}
        </div>
      </div>
    );
  }
}

export default XMRecord;
