import React from 'react'
/**
 * 音频基础组件类
 * props：
 *   src: 音频源地址
 *   lastTime: xx, 上次播放时间
 *   skipBegin: 忽略片头，true/false 
 *   onmeta: 加载资源，可获取如视频长度等信息 父级方法实现
 *   onloaded: 加载完音频，可播放方法 父级方法实现
 *   onloading: 加载中音频 父级方法实现
 *   onplay: 播放音频 父级方法实现
 *   onpause: 暂停播放 父级方法实现
 *   ontime: 
 * 外部可用：
 *   duration
 *   seek
 *   play
 *   pause
 * 
 * 
 * 问题：
 *  1. 华为 P7；小米 自带浏览器，不支持 倍速
 *  2. 音频 跳跃时，可能刷新音频，导致currentTime重新开始
 *  3. 外观不够美化，进度条 不能拖动
 *  4. 图片放大 这个插件也需要集成化
 *  5. 
 */
class Audio extends React.Component {
  static SKIP_SECS = 7; // 片头7s
  /**
   * 构造函数
   */
  constructor(props) {
    /* 继承属性 */
    super(props);
    /* 缓存音频 音频列表 */ 
    this.playList = [];
    /* 音频列表中，播放第几个 */
    this.audioIndex = 0;
    // console.log('diaoyong', this.playList);
    /* 当前所在播放时间 */
    this.time = 0;
    this.stepTimer = null; //time计时器
    // this.lastSeekTime = 0; // 记录上一次 seek时，存储的时间值
  }
  /**
   * 组件渲染前
   */
  componentWillMount() {
    /* 组件渲染前 加载Audio对象并加载音频 */
    this.getAudioObject();
    this.skipBeginAndPlay();
  }
  /**
   * 组件渲染后
   */
  componentDidMount() {
    // 组件创建完成 执行 音频播放
    // this.audioPlay(0);
  }
  componentWillReceiveProps(nextProps) {
    // console.log(12222);
    // if (nextProps.src !== this.props.src) {
    //     // 暂停当前sound
    //     let sound = this.getAudioObject();
    //     if (sound && sound.playing()) {
    //         sound.pause();
    //     }
    //     // 检查是否已存在
    //     let existIndex = findIndex(this.playList, {src: nextProps.src});
    //     if (existIndex < 0) {
    //         existIndex = this.playList.length;
    //         this.playList.push({src: nextProps.src, howl: null, time: 0});
    //     }
    //     this.audioPlay(existIndex);
    // }
  }
  componentWillUnmount() {
    this.getAudioObject().pause();
  }
  shouldComponentUpdate(nextProps, nextState) {
      return false;
  }

  // 第一播放，跳过片头，同时考虑lastTime
  skipBeginAndPlay() {
    let lastTime = this.props.lastTime || 0;
    if (this.props.skipBegin) { lastTime = Math.max(lastTime, Audio.SKIP_SECS); }
    if (lastTime) {
      // if (lastTime > sound.duration() - 10) { lastTime = 0; } // 最后10s不执行跳转lastTime
      // if (cur < lastTime) { // 多次调用，如果当前播放时间大于lastTime时，应该终止播放
        this.seek(lastTime);
      // }
    }
  }
  // 无参数时，播放当前index音频到对应位置。
  // index 要播放的序号
  audioPlay (index) {
    this.audioIndex = index;
    this.time = 0;

    this.skipBeginAndPlay();
  }
  step() {
      clearTimeout(this.stepTimer);

      let sound = this.getAudioObject();
      if (!sound) {return;}
      let seek = Math.round(sound.seek() || 0);
      let playing = sound.playing();
      if (seek !== this.time) {
          this.time = seek;
          this.props.ontime(seek);
      }
      if (playing) {
          this.stepTimer = setTimeout(this.step, 300);
      }
  }
  stepPause() {
      clearTimeout(this.stepTimer);
      this.props.onpause();
  }

  /**
   * 搜寻点击进度条某个位置 跳播方式
   * @param {number} s 传入当前需要改变的时间 
   */
  seek(s) {
    /**
     * 设置时，需要判断是否在seekable的范围内，不在，等待缓冲 
     * 如果在了，就可以设置 -- 华为手机 就是不行，设置 可能会断，重新加载音频
     */
    let _audio = this.getAudioObject(), i = 0;
    // if (!/android/gi.test(navigator.userAgent)) {
    if ('fastSeek' in _audio) {
      _audio.fastSeek(s); // 改变audio.currentTime的值
      return ;
    }
    this.pause();
    _audio.currentTime = s;
    this.play();
    // } else {
    //   for (i=0; i<_audio.seekable.length; i++) {
    //     if (_audio.seekable.start(i) <= s && s >= _audio.seekable.end(i)) {
    //       break;
    //     }
    //   }
    //   if (i < _audio.seekable.length) {
    //     _audio.currentTime = s;
    //   } else {
    //     _audio.buffered.end(_audio.buffered.length - 1);
    //   }
    // }

  }

  /**
   * 返回视频长度
   */
  getDuration() {
    return this.getAudioObject().duration || 0;
  }
  /**
   * 开始播放
   */
  play() {
    this.getAudioObject().play();
  }
  /**
   * 播放暂停
   */
  pause() {
    this.getAudioObject().pause();
  }
  /**
   * 播放速率改变
   * @param {float} n 速率值，每次加0.5 
   */
  rate(n) {
    this.getAudioObject().defaultPlaybackRate = n
    this.getAudioObject().playbackRate = n
  }
  /**
   * render渲染
   */
  render () {
    return null
  }
  /**
   * 获取 Audio对象
   * 内部创建一个 音频对象
   */
  getAudioObject() {
    /* 在缓存音频列表里，获取对应要播放的音频对象 */
    let playItem = this.playList[this.audioIndex];
    /* 如果音频列表里没有 */
    if (!playItem) {
      this.playList[this.audioIndex] = {src: this.props.src, obj: null, time: 0};
      playItem = this.playList[this.audioIndex];
    }
    let _mediaAudio = playItem.obj;
    /* 如果缓存中没有音频对象 */
    if (!_mediaAudio) {
      /* 创建一个Audio对象 */
      _mediaAudio = document.createElement("audio");
      _mediaAudio.src = playItem.src; // 资源src加载
      _mediaAudio.preload = 'auto'; // none:不预载; metadata:仅仅缓冲文件的元数据; auto:缓冲音频文件
      _mediaAudio.autoPlay = true;
      _mediaAudio.load(); // 重新加载src指定的资源 

      _mediaAudio.loadAll = false; // 可能存在缓存，如果从缓存中获取，那么歌曲就全部加载完成了，就不再需要监听progress事件，虽然它还会继续加载

      /* 开始请求 顺序 1 */
      _mediaAudio.addEventListener('loadstart', () => {

      }, false);
      /* 正在请求 顺序 2, 这个比较特殊，有缓存时，它还会请求 */
      _mediaAudio.addEventListener('progress', () => {
        /* 父级事件，告诉父级音频在加载中 */
        !_mediaAudio.loadAll && this.props.onloading();
        // console.log('loading', !_mediaAudio.loadAll);
      }, false);
      /* 资源长度改 顺序 3 */
      _mediaAudio.addEventListener('durationchange', () => {
        /* 父级事件，告诉父级一些资源信息 华为原生浏览器上，播放前loadedmetadata事件监听，获取不到duration信息 */
        this.props.onmeta();
      }, false);
      /* 可以播放，但中途可能因为加载而暂 顺序 4 */
      _mediaAudio.addEventListener('canplay', () => {
        /* 父级事件，告诉父级音频加载完成 */
        this.props.onloaded();
        _mediaAudio.play();
      }, false);
      /* 可以播放，歌曲全部加载完毕 顺序 5 */
      _mediaAudio.addEventListener('canplaythrough', () => {
        /* 歌曲全部加载 */
        _mediaAudio.loadAll = true;
        /* 父级事件，告诉父级音频加载完成 */
        this.props.onloaded();
        _mediaAudio.play();
      }, false);

      /* play()和autoplay 开始播放时，触发 但并未真正开始播放 */
      _mediaAudio.addEventListener('play', () => {
        /* 父级事件，告诉父级音频正在播放 */
        this.props.onplay();
        /* 父级事件，告诉父级音频在加载中 */
        this.props.onloading();
      }, false);
      /* playing 开始播放时，触发，真正开始播放 */
      _mediaAudio.addEventListener('playing', () => {
        /**
         * 0	HAVE_NOTHING	没有关于音频/视频是否就绪的信息
         * 1	HAVE_METADATA	关于音频/视频就绪的元数据
         * 2	HAVE_CURRENT_DATA	关于当前播放位置的数据是可用的，但没有足够的数据来播放下一帧/毫秒
         * 3	HAVE_FUTURE_DATA	当前及至少下一帧的数据是可用的
         * 4	HAVE_ENOUGH_DATA	可用数据足以开始播放 
         */
        if (_mediaAudio.readyState >= 2) {
          /* 父级事件，告诉父级音频加载完成 */
          this.props.onloaded();
        }
      }, false);
      /* pause() 暂停播放时，触发 */
      _mediaAudio.addEventListener('pause', () => {
        /* 父级事件，告诉父级音频暂停 */
        this.props.onpause();
      }, false);
      /* 获取一些预设信息，事件监听 */
      _mediaAudio.addEventListener('loadedmetadata', () => {
        /* 父级事件，告诉父级一些资源信息 */
        this.props.onmeta();
      }, false);
      // waiting error abort
      /* 播放时间改变时，实时改变进度条 */
      _mediaAudio.addEventListener('timeupdate', () => {
        /* 父级事件，告诉父级当前播放位置 */
        this.props.ontime(_mediaAudio.currentTime);
        // console.log('play');
      }, false);
      
      

      
      /* 设置playbackRate，触发事件ratechange，播放速率改变 */
      _mediaAudio.addEventListener('ratechange', () => {
        // alert(this.getAudioObject().playbackRate)
      }, false);
      /* 设置currentTime，触发事件seeking，寻找中 */
      _mediaAudio.addEventListener('seeking', () => {
        /* 父级事件，告诉父级音频在加载中 */
        this.props.onloading();
      }, false);
      /* 设置currentTime，触发事件seeked，寻找完成 */
      _mediaAudio.addEventListener('seeked', () => {
        /* 父级事件，告诉父级音频加载完成 */
        this.props.onloaded();
      }, false);
      playItem.obj = _mediaAudio;
    }
    return _mediaAudio;
  }
}

module.exports = Audio;
