import React, { useState, useEffect, useMemo, useCallback } from 'react'
import IconFont from '../iconfont'
import Slider from '../slider'
import { dateFormat } from '../util'
import EventName from '../event/eventName'
import PropTypes from 'prop-types'
import { computedTimeAndIndex } from './utils'
import '../style/time-line.less'
import { useLatest } from 'ahooks'

const computedLineList = (historyList) => {
  const duration = historyList.duration
  return historyList.fragments.map((v) => {
    return {
      disabled: !v.file,
      size: ((v.end - v.begin) / duration) * 100,
    }
  })
}

function TineLine({ event, api, visibel, historyList, playIndex, seekTo, defaultTime }) {
  const [state, setState] = useState({ duration: 1, currentTime: defaultTime, buffered: 0, isEnd: false })
  const { currentTime, buffered, isEnd } = state
  const latestState = useLatest(state)
  useEffect(() => setState((old) => ({ ...old, currentTime: defaultTime })), [defaultTime])
  useEffect(() => {
    const getDuration = () => setState((old) => ({ ...old, duration: api.getDuration() }))
    const getCurrentTime = () => setState((old) => ({ ...old, currentTime: api.getCurrentTime(), buffered: api.getSecondsLoaded() }))
    const getBuffered = () => setState((old) => ({ ...old, buffered: api.getSecondsLoaded() }))
    const historyPlayEnd = () => setState((old) => ({ ...old, isEnd: true }))
    const reload = () => setState((old) => ({ ...old, isEnd: false, currentTime: api.getCurrentTime() }))
    const seekendPlay = () => api.play()
    const fastForwardWithSeek = (second) => {
      const { fragments, beginDate } = historyList
      let fragmentBengin = (fragments[playIndex]?.begin || 0)
      const latestCurrentTime = latestState.current.currentTime
      let newCurrentTime = fragmentBengin + latestCurrentTime + second
      let seektime = beginDate + (newCurrentTime) * 1000
      const [index, time] = computedTimeAndIndex(historyList, newCurrentTime)
      seekTo(newCurrentTime, index, seektime)
    }



    // // 当视频开始加载时
    // event.addEventListener('loadstart', function () {
    //   console.log('Loading the video...');
    // });

    // // 当视频的元数据加载完毕
    // event.addEventListener('loadedmetadata', function () {
    //   console.log('loadedmetadata');
    // });

    // // 当可以播放，但可能需要缓冲
    // event.addEventListener('canplay', function () {
    //   console.log('Can play through, but may need to buffer.');
    // });

    // // 当预计可以在不停止的情况下播放视频至结尾
    // event.addEventListener('canplaythrough', function () {
    //   console.log('Can play through without stopping for buffering.');
    // });

    // // 当正在下载视频数据
    // event.addEventListener('progress', function (e) {
    //   console.log(e);
    //   console.log('Downloading...');
    // });

    // // 当视频播放到可以流畅播放时
    // event.addEventListener('loadeddata', function () {
    //   console.log('Enough data available to start playing.');
    // });

    // // 当视频播放到可以流畅播放且已经播放到视频结束时
    // event.addEventListener('ended', function () {
    //   console.log('Video has ended.');
    // });

    // // 当视频因为错误无法播放时
    // event.addEventListener('error', function () {
    //   console.log('Error loading the video.');
    // });

    // // 当用户已经停止视频的加载
    // event.addEventListener('pause', function () {
    //   console.log('Video is paused.');
    // });

    // // 当用户开始播放视频
    // event.addEventListener('play', function () {
    //   console.log('Video is playing.');
    // });

    // // 当用户开始播放视频至结尾
    // event.addEventListener('playing', function (e) {
    //   console.log(e)
    //   console.log('Playback has begun.');
    // });

    // // 当视频的缓冲已加载足够数据，可以进行播放
    // event.addEventListener('seeked', function () {
    //   console.log('Seek operation completed.');
    // });

    // // 当视频的缓冲正在进行，即将开始播放
    // event.addEventListener('seeking', function () {
    //   console.log('Seek operation is in progress.');
    // });
    // // 当视频的缓冲正在进行，即将开始播放
    // event.addEventListener('timeupdate', function (e) {
    //   console.log(e);
    //   console.log('timeupdate');
    // });
    // event.addEventListener('waiting', function (e) {
    //   console.log(e);
    //   console.log('waiting');
    // });
    // event.addEventListener('seeking', function () {
    //   console.log('seeking');
    // });
    // event.addEventListener('stalled', function () {
    //   console.log('stalled');
    // });
    // event.addEventListener('error', function () {
    //   console.log('error');
    // });



    event.addEventListener('loadedmetadata', getDuration)
    event.addEventListener('durationchange', getDuration)
    event.addEventListener('timeupdate', getCurrentTime)
    event.addEventListener('progress', getBuffered)
    event.addEventListener('suspend', getBuffered)
    event.addEventListener('seeked', seekendPlay)
    event.on(EventName.HISTORY_PLAY_END, historyPlayEnd)
    event.on(EventName.FAST_FORWARD_WITH_SEEK, fastForwardWithSeek)
    event.on(EventName.RELOAD, reload)

    return () => {
      event.removeEventListener('loadedmetadata', getDuration)
      event.removeEventListener('durationchange', getDuration)
      event.removeEventListener('timeupdate', getCurrentTime)
      event.removeEventListener('progress', getBuffered)
      event.removeEventListener('suspend', getBuffered)
      event.removeEventListener('seeked', seekendPlay)
      event.off(EventName.HISTORY_PLAY_END, historyPlayEnd)
      event.off(EventName.FAST_FORWARD_WITH_SEEK, fastForwardWithSeek)
      event.off(EventName.RELOAD, reload)
    }
  }, [event, api])
  const changePlayTime = useCallback(
    (percent) => {
      const currentTime = percent * historyList.duration //修正一下误差
      const [index, time] = computedTimeAndIndex(historyList, currentTime)
      if (currentTime < latestState.current.buffered) {
        api.seekTo(currentTime)
      } else {
        seekTo(currentTime, index, historyList.beginDate + currentTime * 1000)
        setState((old) => ({ ...old, isEnd: false }))

      }
    },
    [historyList]
  )
  const renderTimeLineTips = (percent) => {
    const currentTime = percent * historyList.duration * 1000
    const date = dateFormat(historyList.beginDate + currentTime)
    return <span>{date}</span>
  }

  const lineList = useMemo(() => computedLineList(historyList), [historyList])
  const currentLine = useMemo(() => lineList.filter((_, i) => i < playIndex).map((v) => v.size), [playIndex, lineList])
  const currentIndexTime = useMemo(() => (currentLine.length === 0 ? 0 : currentLine.length > 1 ? currentLine.reduce((p, c) => p + c) : currentLine[0]), [currentLine])
  const playPercent = useMemo(() => {
    let count = (currentTime / historyList.duration) * 100 + currentIndexTime
    if (count >= 100) {
      count = 100
    }
    return count
  }, [currentIndexTime, historyList, currentTime])
  const bufferedPercent = useMemo(() => (buffered / historyList.duration) * 100 + currentIndexTime, [historyList, currentIndexTime, buffered])

  return (
    <div className={`video-time-line-layout ${!visibel ? 'hide-time-line' : ''}`}>
      <IconFont type="lm-player-PrevFast" onClick={() => api.backWind()} className="time-line-action-item" />
      <Slider className="time-line-box" currentPercent={isEnd ? '100' : playPercent} availablePercent={bufferedPercent} onChange={changePlayTime} renderTips={renderTimeLineTips}>
        <>
          {lineList.map((v, i) => {
            const currentSizeLine = lineList.filter((v, i2) => i2 < i).map((v) => v.size)
            const currentIndexSize = currentSizeLine.length === 0 ? 0 : currentSizeLine.length > 1 ? currentSizeLine.reduce((p, c) => p + c) : currentSizeLine[0]
            const currentSize = v.size || 0
            return (
              <div className={`history-time-line-item ${v.disabled ? 'history-time-line-disabled' : ''}`} key={i} style={{ width: `${currentSize}%`, left: `${currentIndexSize}%` }} />
            )
          })}
        </>
      </Slider>
      <IconFont type="lm-player-NextFast_Light" onClick={() => {
        api.fastForward()
      }} className="time-line-action-item" />
    </div>
  )
}

TineLine.propTypes = {
  event: PropTypes.object,
  api: PropTypes.object,
  changePlayIndex: PropTypes.func,
  playIndex: PropTypes.number,
  historyList: PropTypes.array,
  seekTo: PropTypes.func,
  visibel: PropTypes.bool,
}

export default TineLine
