import { defineComponent, nextTick, onMounted, reactive, toRefs, watch } from "vue"
import "plyr/dist/plyr.css"
import Plyr from "plyr"
import styles from "./index.module.scss"

import icons from "../../image/icons.json"

const { iconVideoBg } = icons
// eslint-disable-next-line @typescript-eslint/no-var-requires
const iconLoopActive = require("../../image/iconLoopActive.png")
// eslint-disable-next-line @typescript-eslint/no-var-requires
const iconLoop = require("../../image/iconLoop.png")
// eslint-disable-next-line @typescript-eslint/no-var-requires
const iconPause = require("../../image/iconPause.png")
// eslint-disable-next-line @typescript-eslint/no-var-requires
const iconPlay = require("../../image/iconPlay.png")
// eslint-disable-next-line @typescript-eslint/no-var-requires
const iconSpeed = require("../../image/iconSpeed.png")
import { ElSlider } from "element-plus"

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 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}">
                        <div 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}" />
                        </div>
                        <div id="${loopBtnId}" class="${styles.actionBtn} ${styles.loopBtn}">
                            <img class="loop" style="width:54px;height:44px;" src="${iconLoop}" />
                            <img class="loopActive" style="width:58px;height:44px;" src="${iconLoopActive}" />
                        </div>
                        <div style="position: relative">
                          <div id="${speedBtnId}" class="${styles.actionBtn} ${styles.speedBtn}">
                              <img class="loop" src="${iconSpeed}" />
                          </div>
                        </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
      }
      const getVideoItem = () => {
         return data.videoItem
      }
      expose({
         getVideoRef,
         getVideoItem
      })

      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>
                  <ElSlider
                     class={styles.el_slider}
                     style={{ padding: "12px 0" }}
                     min={0.5}
                     max={1.5}
                     step={0.1}
                     v-model={data.defaultSpeed}
                     vertical
                     height={"82px"}
                     onChange={() => {
                        if (data.videoItem) {
                           data.videoItem.speed = data.defaultSpeed
                        }
                     }}
                  >
                     {{
                        button: () => (
                           <div class={styles.sliderPoint}>
                              {data.defaultSpeed}
                              <span>x</span>
                           </div>
                        )
                     }}
                  </ElSlider>
                  <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>
      )
   }
})
