<template>
  <h1>Watch</h1>
  <Card class="p-text-center" v-if="!state.active">
    <template #content>
      <ProgressSpinner />
      <h2>Waiting for connections. Please wait...</h2>
    </template>
  </Card>
  <div v-show="state.active">
    <Card >
      <template #content>
        <ProgressBar class="p-mb-2" :value="progress" :showValue="false" />
        <video ref="player" controls="true"></video>
      </template>
    </Card>
    <Card>
      <template #title>
        Properties
      </template>
      <template #content>
        <div class="p-grid">
          <div class="p-col-12 p-md-4">
            <h5>Filename</h5>
            <span>{{video.name}}</span>
          </div>
          <div class="p-col-12 p-md-4">
            <h5>Duration</h5>
            <span>{{video.hDuration}}</span>
          </div>
          <div class="p-col-12 p-md-4">
            <h5>File size</h5>
            <span>{{video.hSize}}</span>
          </div>
          <div class="p-col-12">
            <h5>ID</h5>
            <div class="p-fluid">
              <InputText class="p-inputtext-sm" :value="state.infoHash" disabled />
            </div>
          </div>
        </div>
      </template>
    </Card>
    <WireStatistics :wireStatistics="wireStatistics"/>
  </div>
</template>

<script>
import { inject, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { useToast } from 'primevue/usetoast'
import prettyBytes from 'pretty-bytes'
import prettyMilliseconds from 'pretty-ms'
import WebTorrent from 'webtorrent/webtorrent.min.js'
import generateWireStatistics from '@/helpers/wire-statistics'

export default {
  props: {
    id: {
      required: true,
      type: String
    }
  },
  setup (props) {
    const router = useRouter()
    const toast = useToast()
    const trackers = inject('trackers')
    var webTorrent = null
    const player = ref(null)
    const progress = ref()
    const video = reactive({
      file: null,
      name: '',
      size: 0,
      duration: 0,
      hSize: '',
      hDuration: ''
    })
    const state = reactive({
      active: false,
      torrent: null,
      infoHash: '',
      downloaded: 0,
      wires: []
    })
    const wireStatistics = reactive([])

    onBeforeMount(() => {
      if (!/^([a-f0-9]{40})$/.test(props.id)) {
        toast.add({ severity: 'error', summary: 'Bad ID', detail: 'Please enter a valid ID.', life: 3000 })
        router.push('/join')
      }
    })

    onMounted(() => {
      webTorrent = new WebTorrent()
      downloadVideo(props.id)
    })

    onBeforeUnmount(() => {
      if (webTorrent) {
        webTorrent.destroy()
      }
    })

    const downloadVideo = (infoHash) => {
      webTorrent.add(infoHash, { announce: trackers }, torrent => {
        torrent.on('wire', () => {
          updateWireStatistics()
          toast.add({ severity: 'info', summary: 'New watcher', detail: 'Someone has joined your screen.', life: 3000 })
        })

        torrent.on('noPeers', () => {
          toast.add({ severity: 'warning', summary: 'No peers', detail: 'No one is sharing this video at the moment.', life: 3000 })
        })

        torrent.on('upload', bytes => {
          updateWireStatistics()
        })

        torrent.on('download', bytes => {
          if (!state.active) {
            state.active = true
            initialise(torrent)
          }
          state.downloaded += bytes
          progress.value = state.downloaded / video.size * 100
          updateWireStatistics()
        })
      })
    }

    const initialise = (torrent) => {
      state.torrent = torrent
      state.infoHash = torrent.infoHash
      state.wires = torrent.wires

      var file = torrent.files.find(file => {
        return file.name.endsWith('.mp4')
      })

      video.file = file
      video.name = file.name
      video.size = file.length
      video.hSize = prettyBytes(file.length)
      player.value.addEventListener('loadedmetadata', (e) => {
        video.duration = e.target.duration
        video.hDuration = prettyMilliseconds(e.target.duration * 1000)
      })

      file.renderTo(player.value)
    }

    const updateWireStatistics = () => {
      var newWireStatistics = generateWireStatistics(state.wires)
      wireStatistics.splice.apply(wireStatistics, [0, newWireStatistics.length].concat(newWireStatistics))
    }

    return {
      player,
      video,
      state,
      progress,
      wireStatistics
    }
  }
}
</script>

<style>

</style>
