<template>
  <div :id="containerId" ref="containerRef" class="ezviz-hls-player" />
</template>

<script>
import HlsPlayer from "@ezuikit/player-hls"

let containerSeq = 0

export default {
  name: "EzvizHlsPlayer",
  props: {
    url: {
      type: String,
      default: ""
    }
  },
  data() {
    containerSeq += 1
    return {
      containerId: `ezviz-hls-player-${containerSeq}`,
      resizeObserver: null
    }
  },
  computed: {
    decoderStaticPath() {
      if (process.env.NODE_ENV === "production") {
        return "/client/"
      }
      return "/"
    }
  },
  watch: {
    url(val) {
      this.rebuildPlayer(val)
    }
  },
  created() {
    this.hlsPlayer = null
    this.onPlayerParsed = null
  },
  mounted() {
    this.bindResizeObserver()
    if (this.url) {
      this.$nextTick(() => {
        this.initPlayer(this.url)
      })
    }
  },
  beforeDestroy() {
    this.unbindResizeObserver()
    this.destroyPlayer()
  },
  methods: {
    getContainerSize() {
      const el = this.$refs.containerRef
      if (!el) {
        return { width: 0, height: 0 }
      }
      const parent = el.parentElement
      const width = el.clientWidth || (parent && parent.clientWidth) || el.offsetWidth || 0
      const height = el.clientHeight || (parent && parent.clientHeight) || el.offsetHeight || 0
      return { width, height }
    },
    bindResizeObserver() {
      if (typeof ResizeObserver === "undefined") {
        return
      }
      this.resizeObserver = new ResizeObserver(() => {
        this.syncPlayerSize()
      })
      this.$nextTick(() => {
        const el = this.$refs.containerRef
        if (el && el.parentElement) {
          this.resizeObserver.observe(el.parentElement)
        }
      })
    },
    unbindResizeObserver() {
      if (this.resizeObserver) {
        this.resizeObserver.disconnect()
        this.resizeObserver = null
      }
    },
    syncPlayerSize() {
      if (!this.hlsPlayer || typeof this.hlsPlayer.resize !== "function") {
        return
      }
      const { width, height } = this.getContainerSize()
      if (width > 0 && height > 0) {
        this.hlsPlayer.resize(width, height)
      }
    },
    bindPlayerEvents() {
      if (!this.hlsPlayer || !this.hlsPlayer.event) {
        return
      }
      this.onPlayerParsed = () => {
        if (typeof this.hlsPlayer.play === "function") {
          this.hlsPlayer.play().catch(() => {
            this.$emit("error")
          })
        }
      }
      this.hlsPlayer.event.on("parsed", this.onPlayerParsed)
    },
    unbindPlayerEvents() {
      if (this.hlsPlayer && this.hlsPlayer.event && this.onPlayerParsed) {
        this.hlsPlayer.event.off("parsed", this.onPlayerParsed)
      }
      this.onPlayerParsed = null
    },
    destroyPlayer() {
      this.unbindPlayerEvents()
      if (this.hlsPlayer) {
        try {
          this.hlsPlayer.destroy()
        } catch (e) {
          // ignore teardown errors
        }
        this.hlsPlayer = null
      }
      const el = this.$refs.containerRef
      if (el) {
        el.innerHTML = ""
      }
    },
    rebuildPlayer(url) {
      this.destroyPlayer()
      if (url) {
        this.$nextTick(() => {
          this.initPlayer(url)
        })
      }
    },
    initPlayer(url, retryCount = 0) {
      const text = url != null ? String(url).trim() : ""
      if (!text) {
        return
      }
      const el = document.getElementById(this.containerId)
      if (!el) {
        return
      }
      el.innerHTML = ""
      const { width, height } = this.getContainerSize()
      if (width <= 0 || height <= 0) {
        if (retryCount < 8) {
          requestAnimationFrame(() => {
            this.initPlayer(url, retryCount + 1)
          })
        }
        return
      }
      this.hlsPlayer = new HlsPlayer({
        id: this.containerId,
        url: text,
        staticPath: this.decoderStaticPath,
        isLive: true,
        autoPlay: true,
        width,
        height
      })
      this.bindPlayerEvents()
      this.hlsPlayer.play().catch(() => {
        this.$emit("error")
      })
    }
  }
}
</script>

<style scoped>
.ezviz-hls-player {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;
}

.ezviz-hls-player ::v-deep .ezui-player-container,
.ezviz-hls-player ::v-deep .ezui-hls-container {
  width: 100% !important;
  height: 100% !important;
}

.ezviz-hls-player ::v-deep canvas,
.ezviz-hls-player ::v-deep video {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain;
}
</style>
