<template>
  <h1 class="mt-3 is-size-3 is-clickable is-unselectable" @click="showQueue = !showQueue" v-if="hasQueuedItems">
    <span class="icon-text title is-4">
      <span class="icon">
        <i class="fas" :class="showQueue ? 'fa-solid fa-arrow-up' : 'fa-solid fa-arrow-down'" />
      </span>
      <span>Queue <span v-if="hasQueuedItems">({{ stateStore.count('queue') }})</span></span>
    </span>
  </h1>

  <div v-if="showQueue">
    <div class="columns is-multiline is-mobile has-text-centered" v-if="hasQueuedItems">
      <div class="column is-half-mobile" v-if="'cards' === display_style">
        <button type="button" class="button is-fullwidth is-ghost" @click="masterSelectAll = !masterSelectAll">
          <span class="icon-text is-block">
            <span class="icon">
              <i class="fas" :class="!masterSelectAll ? 'fa-regular fa-square-check' : 'fa-regular fa-square'" />
            </span>
            <span v-if="!masterSelectAll">Select All</span>
            <span v-else>Unselect All</span>
          </span>
        </button>
      </div>
      <div class="column is-half-mobile" v-if="('cards' === display_style || hasSelected)">
        <button type="button" class="button is-fullwidth is-danger" :disabled="!hasSelected" @click="cancelSelected">
          <span class="icon-text is-block">
            <span class="icon">
              <i class="fa-solid fa-trash-can" />
            </span>
            <span>Cancel Selected</span>
          </span>
        </button>
      </div>
    </div>

    <div class="columns is-multiline" v-if="'list' === display_style">
      <div class="column is-12" v-if="hasQueuedItems">
        <div class="table-container is-responsive">
          <table class="table is-striped is-hoverable is-fullwidth is-bordered"
            style="min-width: 1300px; table-layout: fixed;">
            <thead>
              <tr class="has-text-centered is-unselectable">
                <th width="5%" v-tooltip="masterSelectAll ? 'Unselect all' : 'Select all'">
                  <a href="#" @click.prevent="masterSelectAll = !masterSelectAll">
                    <span class="icon-text is-block">
                      <span class="icon">
                        <i class="fa-regular"
                          :class="{ 'fa-square-check': !masterSelectAll, 'fa-square': masterSelectAll }" />
                      </span>
                    </span>
                  </a>
                </th>
                <th width="40%">Video Title</th>
                <th width="15%">Status</th>
                <th width="20%">Progress</th>
                <th width="15%">Created</th>
                <th width="10%">Actions</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="item in stateStore.queue" :key="item._id">
                <td class="has-text-centered is-vcentered">
                  <label class="checkbox is-block">
                    <input class="completed-checkbox" type="checkbox" v-model="selectedElms"
                      :id="'checkbox-' + item._id" :value="item._id">
                  </label>
                </td>
                <td class="is-text-overflow is-vcentered">
                  <div class="is-inline is-pulled-right" v-if="item.downloaded_bytes || item.extras?.duration">
                    <span class="tag" v-if="item.downloaded_bytes">{{ formatBytes(item.downloaded_bytes) }}</span>
                    <span class="tag is-info" v-if="item.extras?.duration">
                      {{ formatTime(item.extras.duration) }}
                    </span>
                  </div>
                  <div v-if="showThumbnails && item.extras?.thumbnail">
                    <FloatingImage :image="uri('/api/thumbnail?url=' + encodePath(item.extras.thumbnail))"
                      :title="item.title">
                      <div class="is-text-overflow">
                        <NuxtLink target="_blank" :href="item.url">{{ item.title }}</NuxtLink>
                      </div>
                    </FloatingImage>
                  </div>
                  <template v-else>
                    <div class="is-text-overflow" v-tooltip="item.title">
                      <NuxtLink target="_blank" :href="item.url">{{ item.title }}</NuxtLink>
                    </div>
                  </template>
                </td>
                <td class="has-text-centered is-text-overflow is-unselectable">
                  <span class="icon-text">
                    <span class="icon" :class="setIconColor(item)">
                      <i class="fas fa-solid" :class="setIcon(item)" />
                    </span>
                    <span v-text="setStatus(item)" />
                  </span>
                </td>
                <td>
                  <div class="progress-bar is-unselectable">
                    <div class="progress-percentage">{{ updateProgress(item) }}</div>
                    <div class="progress" :style="{ width: percentPipe(item.percent) + '%' }"></div>
                  </div>
                </td>
                <td class="has-text-centered is-text-overflow is-unselectable">
                  <span v-tooltip="moment(item.datetime).format('MMMM Do YYYY, h:mm:ss a')"
                    :data-datetime="item.datetime" v-rtime="item.datetime" />
                </td>
                <td class="is-vcentered is-items-center">
                  <div class="field is-grouped is-grouped-centered">
                    <div class="control" v-if="isEmbedable(item.url)">
                      <button @click="() => embed_url = getEmbedable(item.url)" v-tooltip="'Play video'"
                        class="button is-danger is-small">
                        <span class="icon"><i class="fa-solid fa-play" /></span>
                      </button>
                    </div>
                    <div class="control">
                      <button class="button is-warning is-small" @click="confirmCancel(item);"
                        v-tooltip="'Cancel download'">
                        <span class="icon"><i class="fa-solid fa-eject" /></span>
                      </button>
                    </div>
                    <div class="control" v-if="item.url && !config.app.basic_mode">
                      <button class="button is-info is-small" @click="emitter('getInfo', item.url)"
                        v-tooltip="'Show video information'">
                        <span class="icon"><i class="fa-solid fa-info" /></span>
                      </button>
                    </div>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>

    <div class="columns is-multiline" v-else>
      <LateLoader :unrender="true" :min-height="showThumbnails ? 475 : 265" class="column is-6"
        v-for="item in stateStore.queue" :key="item._id">
        <div class="card is-flex is-full-height is-flex-direction-column">
          <header class="card-header">
            <div class="card-header-title is-text-overflow is-block" v-tooltip="item.title">
              <NuxtLink target="_blank" :href="item.url">{{ item.title }}</NuxtLink>
            </div>
            <div class="card-header-icon">
              <div class="field is-grouped">

                <div class="control">
                  <span class="tag is-info" v-if="item.extras?.duration">
                    {{ formatTime(item.extras.duration) }}
                  </span>
                </div>
                <div class="control" v-if="!showThumbnails && isEmbedable(item.url)">
                  <NuxtLink @click="embed_url = getEmbedable(item.url)" v-tooltip="'Play video'">
                    <span class="icon has-text-danger"><i class="fa-solid fa-play" /></span>
                  </NuxtLink>
                </div>
                <div class="control">
                  <button @click="hideThumbnail = !hideThumbnail" v-if="thumbnails">
                    <span class="icon"><i class="fa-solid"
                        :class="{ 'fa-arrow-down': hideThumbnail, 'fa-arrow-up': !hideThumbnail }" /></span>
                  </button>
                </div>
                <div class="control">
                  <label class="checkbox is-block">
                    <input class="completed-checkbox" type="checkbox" v-model="selectedElms"
                      :id="'checkbox-' + item._id" :value="item._id">
                  </label>
                </div>
              </div>
            </div>
          </header>
          <div v-if="showThumbnails" class="card-image">
            <figure class="image is-3by1">
              <span v-if="isEmbedable(item.url)" @click="embed_url = getEmbedable(item.url)" class="play-overlay">
                <div class="play-icon embed-icon"></div>
                <img @load="e => pImg(e)" :src="uri('/api/thumbnail?url=' + encodePath(item.extras.thumbnail))"
                  v-if="item.extras?.thumbnail" />
                <img v-else src="/images/placeholder.png" />
              </span>
              <template v-else>
                <img @load="e => pImg(e)" v-if="item.extras?.thumbnail"
                  :src="uri('/api/thumbnail?url=' + encodePath(item.extras.thumbnail))" />
                <img v-else src="/images/placeholder.png" />
              </template>
            </figure>
          </div>
          <div class="card-content is-flex-grow-1">
            <div class="columns is-multiline is-mobile">
              <div class="column is-12">
                <div class="progress-bar is-unselectable">
                  <div class="progress-percentage">{{ updateProgress(item) }}</div>
                  <div class="progress" :style="{ width: percentPipe(item.percent) + '%' }"></div>
                </div>
              </div>
              <div class="column is-half-mobile has-text-centered is-text-overflow is-unselectable">
                <span class="icon-text">
                  <span class="icon" :class="setIconColor(item)">
                    <i class="fas fa-solid" :class="setIcon(item)" />
                  </span>
                  <span v-text="setStatus(item)" />
                </span>
              </div>
              <div class="column is-half-mobile has-text-centered is-text-overflow is-unselectable">
                <span v-tooltip="moment(item.datetime).format('MMMM Do YYYY, h:mm:ss a')" :data-datetime="item.datetime"
                  v-rtime="item.datetime" />
              </div>
              <div class="column is-half-mobile has-text-centered is-text-overflow is-unselectable"
                v-if="item.downloaded_bytes">
                {{ formatBytes(item.downloaded_bytes) }}
              </div>

            </div>
            <div class="columns is-multiline is-mobile">
              <div class="column is-half-mobile">
                <button class="button is-warning is-fullwidth" @click="confirmCancel(item);">
                  <span class="icon"><i class="fa-solid fa-eject" /></span>
                  <span>Cancel</span>
                </button>
              </div>
              <div class="column is-half-mobile" v-if="item.url && !config.app.basic_mode">
                <button class="button is-info is-fullwidth" @click="emitter('getInfo', item.url)">
                  <span class="icon"><i class="fa-solid fa-info" /></span>
                  <span>Information</span>
                </button>
              </div>
            </div>
          </div>
        </div>
      </LateLoader>
    </div>


    <div class="modal is-active" v-if="embed_url">
      <div class="modal-background" @click="embed_url = ''"></div>
      <div class="modal-content is-unbounded-model">
        <EmbedPlayer :url="embed_url" @closeModel="embed_url = ''" />
      </div>
      <button class="modal-close is-large" aria-label="close" @click="embed_url = ''"></button>
    </div>
  </div>
</template>

<script setup>
import moment from 'moment'
import { useStorage } from '@vueuse/core'
import { ucFirst } from '~/utils/index'
import { isEmbedable, getEmbedable } from '~/utils/embedable'

const emitter = defineEmits(['getInfo'])
const props = defineProps({
  thumbnails: {
    type: Boolean,
    default: true
  }
})
const config = useConfigStore()
const stateStore = useStateStore()
const socket = useSocketStore()
const box = useConfirm()

const selectedElms = ref([])
const masterSelectAll = ref(false)
const showQueue = useStorage('showQueue', true)
const hideThumbnail = useStorage('hideThumbnailQueue', false)
const display_style = useStorage('display_style', 'cards')
const showThumbnails = computed(() => props.thumbnails && !hideThumbnail.value)

const embed_url = ref('')

const bg_enable = useStorage('random_bg', true)
const bg_opacity = useStorage('random_bg_opacity', 0.85)

watch(masterSelectAll, (value) => {
  for (const key in stateStore.queue) {
    const element = stateStore.queue[key]
    if (value) {
      selectedElms.value.push(element._id)
    } else {
      selectedElms.value = []
    }
  }
})

const hasSelected = computed(() => selectedElms.value.length > 0)
const hasQueuedItems = computed(() => stateStore.count('queue') > 0)

const setIcon = item => {
  if ('downloading' === item.status && item.is_live) {
    return 'fa-globe fa-spin'
  }

  if ('downloading' === item.status) {
    return 'fa-download'
  }

  if ('postprocessing' === item.status) {
    return 'fa-cog fa-spin'
  }

  if (null === item.status && true === config.paused) {
    return 'fa-pause-circle'
  }

  if (!item.status) {
    return 'fa-question'
  }

  return 'fa-spinner fa-spin'
}

const setStatus = item => {
  if (null === item.status && true === config.paused) {
    return 'Paused'
  }

  if ('downloading' === item.status && item.is_live) {
    return 'Streaming'
  }

  if ('preparing' === item.status) {
    return ag(item, 'extras.external_downloader') ? 'External-DL' : 'Preparing..';
  }

  if (!item.status) {
    return 'Unknown...'
  }

  return ucFirst(item.status)
}

const setIconColor = item => {
  if (item.status === 'downloading') {
    return 'has-text-success'
  }

  if ('postprocessing' === item.status) {
    return 'has-text-info'
  }

  if (null === item.status && true === config.paused) {
    return 'has-text-warning'
  }

  return ''
}

const ETAPipe = value => {
  if (value === null || 0 === value) {
    return 'Live'
  }
  if (value < 60) {
    return `${Math.round(value)}s`
  }
  if (value < 3600) {
    return `${Math.floor(value / 60)}m ${Math.round(value % 60)}s`
  }
  const hours = Math.floor(value / 3600)
  const minutes = value % 3600
  return `${hours}h ${Math.floor(minutes / 60)}m ${Math.round(minutes % 60)}s`
}

const speedPipe = value => {
  if (null === value || 0 === value) {
    return '0KB/s'
  }

  const k = 1024
  const dm = 2
  const sizes = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s', 'PB/s', 'EB/s', 'ZB/s', 'YB/s']
  const i = Math.floor(Math.log(value) / Math.log(k))
  return parseFloat((value / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]
}

const percentPipe = value => {
  if (value === null || 0 === value) {
    return '00.00'
  }
  return parseFloat(value).toFixed(2)
}

const updateProgress = (item) => {
  let string = ''

  if (null === item.status && true === config.paused) {
    return 'Paused'
  }

  if ('postprocessing' === item.status) {
    return 'Post-processors are running.'
  }

  if ('preparing' === item.status) {
    return ag(item, 'extras.external_downloader') ? 'External downloader.' : 'Preparing'
  }

  if (null != item.status) {
    string += item.percent && !item.is_live ? percentPipe(item.percent) + '%' : 'Live'
  }

  string += item.speed ? ' - ' + speedPipe(item.speed) : ' - Waiting..'

  if (null != item.status && item.eta) {
    string += ' - ' + ETAPipe(item.eta)
  }

  return string;
}

const confirmCancel = item => {
  if (true !== box.confirm(`Are you sure you want to cancel (${item.title})?`)) {
    return false
  }
  cancelItems(item._id)
  return true
}

const cancelSelected = () => {
  if (true !== box.confirm('Are you sure you want to cancel selected items?')) {
    return false;
  }
  cancelItems(selectedElms.value)
  selectedElms.value = []
  return true;
}

const cancelItems = item => {
  const items = []

  if (typeof item === 'object') {
    for (const key in item) {
      items.push(item[key])
    }
  } else {
    items.push(item)
  }

  if (items.length < 0) {
    return
  }

  items.forEach(id => socket.emit('item_cancel', id))
}

const pImg = e => e.target.naturalHeight > e.target.naturalWidth ? e.target.classList.add('image-portrait') : null

watch(embed_url, v => {
  if (!bg_enable.value) {
    return
  }
  document.querySelector('body').setAttribute("style", `opacity: ${v ? 1 : bg_opacity.value}`)
})

</script>
