import {
  defineComponent,
  nextTick,
  onMounted,
  reactive,
  render,
  toRefs,
  watch
} from 'vue';
import 'plyr/dist/plyr.css';
import Plyr from 'plyr';
import styles from './index.module.less';

import {
  iconVideoBg,
  iconLoop,
  iconLoopActive,
  iconPlay,
  iconPause,
  iconSpeed
} from '../../image/icons.json';
import { Popup, Slider } from 'vant';
import { useElementBounding } from '@vueuse/core';

export default defineComponent({
  name: 'video-play',
  props: {
    item: {
      type: Object,
      default: () => {
        return {};
      }
    },
    activeModel: {
      type: Boolean,
      default: true
    }
  },
  emits: ['play', 'pause', 'ended', 'close'],
  setup(props, { emit, expose }) {
    const { item } = toRefs(props);
    const data = reactive({
      videoContianerRef: null as unknown as HTMLAudioElement,
      videoState: 'pause' as 'init' | 'play' | 'pause',
      animationState: 'start' as 'start' | 'end',
      videoItem: null as unknown as Plyr,
      speedControl: false,
      speedStyle: {
        left: '1px'
      },
      defaultSpeed: 1 // 默认速度
    });
    const controlID = 'v' + Date.now() + Math.floor(Math.random() * 100);
    const playBtnId = 'play' + Date.now() + Math.floor(Math.random() * 100);
    const loopBtnId = 'loop' + Date.now() + Math.floor(Math.random() * 100);
    const speedBtnId = 'speed' + Date.now() + Math.floor(Math.random() * 100);
    const speedPopoverId =
      'popover' + Date.now() + Math.floor(Math.random() * 100);

    const togglePlay = (e: Event) => {
      e.stopPropagation();
      data.speedControl = false;
      if (!data.videoContianerRef.paused) {
        data.videoItem?.pause();
      } else {
        data.videoContianerRef?.play();
      }
    };
    const toggleLoop = () => {
      data.speedControl = false;
      const loopBtn = document.getElementById(loopBtnId);
      if (!loopBtn || !data.videoItem) return;
      const isLoop = data.videoItem.loop;
      if (isLoop) {
        loopBtn.classList.remove(styles.active);
      } else {
        loopBtn.classList.add(styles.active);
      }
      data.videoItem.loop = !data.videoItem.loop;
    };
    const onDefault = () => {
      document
        .getElementById(controlID)
        ?.addEventListener('click', (e: Event) => {
          e.stopPropagation();
          data.speedControl = false;
          if (data.videoContianerRef.paused) return;
          emit('close');
        });
      document.getElementById(controlID)?.addEventListener('touchmove', () => {
        data.speedControl = false;
        if (data.videoContianerRef.paused) return;
        emit('close');
      });
      document.getElementById(playBtnId)?.addEventListener('click', togglePlay);
      document.getElementById(loopBtnId)?.addEventListener('click', toggleLoop);

      document.getElementById(speedBtnId)?.addEventListener('click', e => {
        e.stopPropagation();
        data.speedControl = !data.speedControl;
      });

      setName();
    };
    const setName = () => {
      const nameEl = document.getElementById('videoItemName');
      if (nameEl) {
        nameEl.innerHTML = item.value.name || '';
      }
    };

    const changePlayBtn = (code: string) => {
      const playBtn = document.getElementById(playBtnId);
      if (!playBtn) return;
      if (code == 'play') {
        playBtn.classList.remove(styles.btnPause);
        playBtn.classList.add(styles.btnPlay);
      } else {
        playBtn.classList.remove(styles.btnPlay);
        playBtn.classList.add(styles.btnPause);
      }
    };
    const controls = `
            <div id="${controlID}" class="plyr__controls bottomFixed ${styles.controls}">
                <div class="${styles.time}">
                    <div class="plyr__time plyr__time--current" aria-label="Current time">00:00</div>
                    <div class="plyr__time plyr__time--duration" aria-label="Duration">00:00</div>
                </div>
                <div class="${styles.slider}">
                    <div class="plyr__progress">
                        <input data-plyr="seek" type="range" min="0" max="100" step="0.01" value="0" aria-label="Seek">
                        <progress class="plyr__progress__buffer" min="0" max="100" value="0">% buffered</progress>
                        <span role="tooltip" class="plyr__tooltip">00:00</span>
                    </div>
                </div>
                <div class="${styles.actions}">
                    <div class="${styles.actionWrap}">
                        <button id="${playBtnId}" class="${styles.actionBtn}">
                            <div class="van-loading van-loading--circular" aria-live="polite" aria-busy="true"><span class="van-loading__spinner van-loading__spinner--circular" style="color: rgb(255, 255, 255);"><svg class="van-loading__circular" viewBox="25 25 50 50"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
                            <img class="${styles.playIcon}" src="${iconPlay}" />
                            <img class="${styles.playIcon}" src="${iconPause}" />
                        </button>
                        <button id="${loopBtnId}" class="${styles.actionBtn} ${styles.loopBtn}" style="margin:0 2px;">
                            <img class="loop" src="${iconLoop}" />
                            <img class="loopActive" src="${iconLoopActive}" />
                        </button>
                        <div style="position: relative">
                          <button id="${speedBtnId}" class="${styles.actionBtn} ${styles.speedBtn}">
                              <img class="loop" src="${iconSpeed}" />
                          </button>
                        </div>
                    </div>
                    <div id="videoItemName"></div>
                </div>
            </div>`;

    onMounted(() => {
      data.videoItem = new Plyr(data.videoContianerRef, {
        autoplay: true,
        controls: controls,
        ratio: '16:9', // 强制所有视频的纵横比
        hideControls: false, // 在 2 秒没有鼠标或焦点移动、控制元素模糊（制表符退出）、播放开始或进入全屏时自动隐藏视频控件。只要移动鼠标、聚焦控制元素或暂停播放，控件就会立即重新出现。
        clickToPlay: false, // 单击（或点击）视频容器将切换播放/暂停
        fullscreen: { enabled: false, fallback: false, iosNative: false } // 不适用全屏
      });

      nextTick(() => {
        onDefault();
      });
    });

    const toggleHideControl = (isShow: boolean) => {
      data.videoItem?.toggleControls(isShow);

      if (!isShow) {
        data.speedControl = isShow;
      }
    };
    watch(
      () => props.activeModel,
      () => {
        toggleHideControl(props.activeModel);
      }
    );

    watch(
      () => props.item,
      () => {
        setName();
        // 设置视屏播放器的默认速度
        if (data.videoItem) data.videoItem.speed = data.defaultSpeed || 1;

        // 切换的时候隐藏
        data.speedControl = false;
      }
    );
    let videoTimer = null as any;
    const handlePlayVideo = () => {
      clearTimeout(videoTimer);
      nextTick(() => {
        data.videoContianerRef.play().catch(err => {
          console.log('🚀 ~ err:', err);
          videoTimer = setTimeout(() => {
            if (err?.message?.includes('play()')) {
              emit('play');
            }
            handlePlayVideo();
          }, 1000);
        });
      });
    };

    let videoErrorTimer = null as any;
    let videoErrorCount = 0;
    const handleErrorVideo = () => {
      if (videoErrorCount > 5) {
        return;
      }
      clearTimeout(videoErrorTimer);
      nextTick(() => {
        videoErrorTimer = setTimeout(() => {
          data.videoContianerRef.src = props.item?.content;

          emit('play');
          data.videoContianerRef.load();
          // eslint-disable-next-line @typescript-eslint/no-unused-vars
          handleErrorVideo();
        }, 1000);
      });
      videoErrorCount++;
    };
    const getVideoRef = () => {
      return data.videoContianerRef;
    };
    expose({
      getVideoRef
    });

    return () => (
      <div class={styles.videoWrap}>
        <video
          ref={el =>
            (data.videoContianerRef = el as unknown as HTMLAudioElement)
          }
          class={styles.itemDiv}
          src={props.item?.content}
          poster={iconVideoBg}
          webkit-playsinline
          playsinline
          x5-video-player-type="h5"
          onLoadedmetadata={() => {
            data.videoState = 'pause';
            changePlayBtn('play');
            nextTick(() => {
              data.videoContianerRef.currentTime = 0;
              nextTick(handlePlayVideo);
            });
          }}
          onPlay={() => {
            videoErrorCount = 0;
            // console.log('开始播放')
            data.videoState = 'play';
            changePlayBtn('pause');
            emit('close');
            emit('play');
            clearTimeout(videoErrorTimer);
          }}
          onPause={() => {
            // console.log('暂停播放')
            data.videoState = 'pause';
            changePlayBtn('play');
            emit('pause');
          }}
          onEnded={() => {
            // console.log('播放结束')
            data.videoState = 'pause';
            changePlayBtn('play');
            emit('ended');
          }}
          onError={handleErrorVideo}></video>

        <div
          style={{
            display: data.speedControl ? 'block' : 'none'
          }}>
          <div
            class={styles.sliderPopup}
            onClick={(e: Event) => {
              e.stopPropagation();
            }}>
            <i
              class={styles.iconAdd}
              onClick={() => {
                if (data.defaultSpeed >= 1.5) {
                  return;
                }

                if (data.videoItem) {
                  data.defaultSpeed = (data.defaultSpeed * 10 + 1) / 10;
                  data.videoItem.speed = data.defaultSpeed;
                }
              }}></i>
            <Slider
              min={0.5}
              max={1.5}
              step={0.1}
              v-model={data.defaultSpeed}
              vertical
              barHeight={5}
              reverse
              onChange={() => {
                if (data.videoItem) {
                  data.videoItem.speed = data.defaultSpeed;
                }
              }}>
              {{
                button: () => (
                  <div class={styles.sliderPoint}>
                    {data.defaultSpeed}
                    <span>x</span>
                  </div>
                )
              }}
            </Slider>
            <i
              class={[styles.iconCut]}
              onClick={() => {
                if (data.defaultSpeed <= 0.5) {
                  return;
                }
                if (data.videoItem) {
                  data.defaultSpeed = (data.defaultSpeed * 10 - 1) / 10;
                  data.videoItem.speed = data.defaultSpeed;
                }
              }}></i>
          </div>
        </div>
      </div>
    );
  }
});
