

class MseVideo {

  get startTime() {
    return this.sourceBuffer && this.sourceBuffer.buffered.length > 0 ? this.sourceBuffer.buffered.start(0) : 0;
  }

  get currentTime() {
    return this.video ? this.video.currentTime : 0;
  }

  get endTime() {
    return this.sourceBuffer && this.sourceBuffer.buffered.length > 0 ? this.sourceBuffer.buffered.end(0) : 0;
  }

  get ready() {
    try {
      if (this.mediaSource.readyState !== 'open') {
        return false;
      }
      const sourceBufferReady = !!this.sourceBuffer && !this.sourceBuffer.updating;
      // 三秒之后播放完成， 准备加载新的视频段, 如果视频有累计延迟的话，视频会暂停
      const willPlayDown = Math.ceil(this.currentTime) + 3 >= Math.floor(this.endTime);
      return sourceBufferReady && willPlayDown;
    } catch (error) {
      return false;
    }
  }

  get realTime() {
    const list = JSON.parse(JSON.stringify(this.playedVideos));
    list.pop();
    const time = list.reduce((p, n) => p + n.timeInterval, 0);
    return time;
  }

  get activeVideo() { // 确定当前应该绘制的数据
    const realCurrentVideo = this.playedVideos
      .find((item) => item.startTime < this.currentTime && item.endTime > this.currentTime);
    return realCurrentVideo;

  }
  playbackRate = 1;
  // 视频必须是编码格式的
  // private mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
  mimeCodec = 'video/mp4; codecs="avc1.42E01E"';
  video = null;
  mediaSource = null;
  sourceBuffer = null;
  timeSign = null;
  error = null;
  currentVideo = null; // 正在处理buf
  playedVideos = []; // 缓存已经播放视频
  willPalyVideos = []; // 缓存未播放视频
  events = new Map();
  intervals = [];

  constructor(video) {
    this.video = video;
    this.playbackRate = 1;
    this.timeSign = null;
    this.clearIntervals();
    clearInterval(this.timeSign);
    this.currentVideo = null;
    this.willPalyVideos = [];
    this.playedVideos = [];
    this.events = new Map();
    this.mediaSource = null;
    this.sourceBuffer = null;
    this.init();
  }

   play({ target }) {
    if (target && !target.paused) {
      target.pause();
    }
    // 视频播放倍率
    target.playbackRate = this.playbackRate;
    target.play();
  }

   pause() {
    const target = this.video;
    if (target && !target.paused) {
      target.pause();
    } else if (target && target.paused) {
      target.play();
    }
  }

   append(videoName, buf, data = []) {
    const [h, m, s, fileType] = videoName.split('/').pop().split(/[-|.]/i);
    const ts = +h * 360 + +m * 60 + +s;

    const lastVideo = this.willPalyVideos[this.willPalyVideos.length - 1];
    if (lastVideo) {
      lastVideo.endTime = ts - lastVideo.ts;
      lastVideo.timeInterval = lastVideo.endTime - lastVideo.startTime;
    }

    if (this.playedVideos.length > 5) { // 清除已播放文件
      this.playedVideos.splice(0, 3);
    }

    this.willPalyVideos.push({
      id: new Date().getTime(),
      buf,
      error: false,
      data,
      startTime: 0,
      endTime: 0,
      ts,
    });
    if (this.events.has('appended')) {
      this.emit('appended', this.videoList);
    }
    this._loadData();
  }

   on(eventName, handle) {
    this.events.set(eventName, handle);
  }

   init() {
    if ('MediaSource' in window && MediaSource.isTypeSupported(this.mimeCodec) && this.video) {
      this.mediaSource = new MediaSource();
      this.video.src = URL.createObjectURL(this.mediaSource);
      this.mediaSource.addEventListener('sourceopen', this._sourceOpen.bind(this));
    }

    if (this.video) {
      this.video.addEventListener('loadeddata', this.play.bind(this), false);
    }
  }

   reload() {
    if (!this.video) {
      return;
    }
    clearInterval(this.timeSign);
    this.timeSign = null;
    this.clearIntervals();
    this.video.removeEventListener('loadeddata', this.play.bind(this), false);
    this.init();
    this._loadData();
    this.error = false;
  }

   _sourceOpen() {
    if (!this.video) {
      return;
    }
    URL.revokeObjectURL(this.video.src);

    this.mediaSource.duration = Infinity;

    if (this.mediaSource.readyState === 'open') {
      this.sourceBuffer = this.mediaSource.addSourceBuffer(this.mimeCodec);
      this.sourceBuffer.mode = 'sequence';

      this.sourceBuffer.addEventListener('updateend', () => {
        if (this.events.has('appended')) {
          this.emit('updateend', this.videoList);
        }
        if (this.error) {
          this.reload();
          return;
        }
        const lastVideo = this.playedVideos[this.playedVideos.length - 2];
        if (!this.error && this.currentTime - 3 >= this.startTime) {
          this.sourceBuffer.remove(this.startTime, this.currentTime - 3);
        }
        const startTime = lastVideo ? lastVideo.error ? 0 : (lastVideo.endTime || 0) : 0;
        this.currentVideo.startTime = startTime;
        this.currentVideo.endTime = this.endTime;
        this.currentVideo.timeInterval = this.currentVideo.endTime - startTime;

        // startTime endTime 设置为当前video的起始结束位置
      });

      this.sourceBuffer.addEventListener('error', (error) => {
        this.error = true;
        this.currentVideo.error = true;
        window.console.log(123, error);
      });
    } else {
      // console.log('媒体未就绪');
    }

  }

   draw(time = this.currentTime, drawLine) {
    if (this.video && this.video.paused) {
      return;
    }
    if (!this.activeVideo) {
      return;
    }
    const {
      data = new Map(), startTime, endTime
    } = this.activeVideo;
    if (startTime > time) {
      return;
    }
    // console.log(this.activeVideo);
    const tsBetween = Math.round((time - startTime) * 1000);
    // const ts = tsBetween - (tsBetween % 10);
    // const objects = data.get(ts);

    const getValue = (ts) => {
      const keys = Array.from((data).keys());
      return keys.find((item, index) => ts >= item && ts < keys[index + 1]) || '';
    };
    const objects = data.get(getValue(tsBetween));
    if (objects && this.events.has('draw')) {
      // console.log(drawLine);
      this.emit('draw', objects, drawLine);
    }
  }

   emit(eventName, ...data) {
    const event = this.events.get(eventName);
    event(...data);
  }

   

   clearIntervals() {
    this.intervals.forEach((item) => {
      clearInterval(item);
    });
  }

   _loadData() {
    if (this.timeSign) {
      clearInterval(this.timeSign);
      this.timeSign = null;
      // return;
    }
    let drawLine = false;
    this.timeSign = setInterval(() => {
      drawLine = !drawLine;
      this.draw(this.currentTime, drawLine);
      if (this.ready) {
        const v = this.willPalyVideos.shift();
        if (!v) {
          clearInterval(this.timeSign);
          this.timeSign = null;
          this.clearIntervals();
          // this.mediaSource.endOfStream(); // 历史视频结尾，实时视频不需要，因为可能随时有新的视频段进来
          return;
        }
        this.currentVideo = v;
        this.playedVideos.push(v);
        this.sourceBuffer.appendBuffer(v.buf);
      }
    }, 40);
    this.intervals.push(this.timeSign);
  }
}
