<template>
  <div class="tw-relative" v-bind="attrs">
    <AMediaDurationCheck
      v-if="media && media.entries.length > 0 && requiredDurationSeconds > 0"
      :media="media"
      :required-duration-seconds="requiredDurationSeconds"
      class="tw-mb-6"
    />

    <AMediaSources
      v-if="sources.length > 0"
      :sources="sources"
      class="tw-mb-6"
      :can-sort="!disabled"
      :can-edit="!disabled"
    />

    <p v-if="disabled && sources.length === 0" class="tw-m-0">
      {{ t('media.editor.noEntries') }}
    </p>

    <section class="tw-mb-6 empty:tw-hidden">
      <AMediaSourceJobQueue :context-key="contextKey" :label="t('media.editor.upload.pending')" />
    </section>

    <fieldset
      v-if="!disabled"
      ref="dropzoneEl"
      class="tw-rounded tw-border-2 tw-flex tw-mb-3 tw-p-6 dark:tw-border-neutral-700"
      :class="{
        'tw-border-teal-600': isOverDropZone && isAllowedToAddFiles,
        'tw-border-gray-200': !isOverDropZone,
        'tw-border-dashed': isAllowedToAddFiles,
      }"
    >
      <div class="tw-place-self-center tw-mx-auto tw-flex tw-flex-col tw-gap-2 tw-items-center">
        <template v-if="isAllowedToAddFiles">
          <icon-system-uicons-file-upload class="tw-text-xl" />
          <p class="tw-mb-0">{{ t('media.editor.control.dropFiles') }}</p>
          <p class="tw-text-gray-400 tw-text-sm tw-mb-1.5 tw-leading-none">
            {{ t('media.editor.control._or') }}
          </p>
        </template>
        <div class="tw-flex tw-flex-wrap tw-justify-center tw-items-center tw-gap-3">
          <button
            v-if="isAllowedToAddFiles"
            type="button"
            class="btn btn-default"
            data-testid="media-editor:open-file-dialog"
            @click="openFileDialog()"
          >
            <icon-iconamoon-file-audio-thin class="tw-flex-none" />
            {{ t('media.editor.control.selectFiles') }}
          </button>
          <APermissionGuard show-permissions="program.add__import">
            <button type="button" class="btn btn-default" @click="importFileFromURL()">
              <icon-formkit-url class="tw-flex-none" />
              {{ t('media.editor.control.importFile') }}
            </button>
            <GetFileImportUrl v-slot="{ resolve }">
              <AFileUrlDialog @save="resolve($event)" @close="resolve(null)" />
            </GetFileImportUrl>
          </APermissionGuard>
        </div>
        <div class="tw-flex tw-flex-wrap tw-justify-center tw-items-center tw-gap-3 tw-mt-1">
          <APermissionGuard show-permissions="program.add__stream">
            <button type="button" class="btn btn-default" @click="addStreamMediaSource()">
              <icon-solar-play-stream-bold class="tw-flex-none" />
              {{ t('media.editor.control.addStream') }}
            </button>
            <GetStreamUrl v-slot="{ resolve }">
              <AStreamURLDialog @save="resolve($event)" @close="resolve(null)" />
            </GetStreamUrl>
          </APermissionGuard>
          <APermissionGuard show-permissions="program.add__line">
            <button type="button" class="btn btn-default" @click="addInputMediaSource">
              <icon-game-icons-jack-plug class="tw-flex-none" />
              {{ t('media.editor.control.addInput') }}
            </button>
            <GetInputUrl v-slot="{ resolve }">
              <AInputUrlDialog @save="resolve($event)" @close="resolve(null)" />
            </GetInputUrl>
          </APermissionGuard>
          <APermissionGuard show-permissions="program.add__m3ufile">
            <button type="button" class="btn btn-default" @click="addM3UMediaSource">
              <icon-ph-playlist-light class="tw-flex-none" />
              {{ t('media.editor.control.addM3u') }}
            </button>
            <GetM3uUrl v-slot="{ resolve }">
              <AM3uUrlDialog @save="resolve($event)" @close="resolve(null)" />
            </GetM3uUrl>
          </APermissionGuard>
        </div>
      </div>
    </fieldset>
  </div>
</template>

<script lang="ts" setup>
import { createTemplatePromise, useDropZone, useFileDialog } from '@vueuse/core'
import { computed, ref, useAttrs, watch } from 'vue'

import { useI18n } from '@/i18n'
import { Media, Show } from '@/types'

import AStreamURLDialog from '@/components/media/AStreamURLDialog.vue'
import AFileUrlDialog from '@/components/media/AFileUrlDialog.vue'
import AInputUrlDialog from '@/components/media/AInputUrlDialog.vue'
import AM3uUrlDialog from '@/components/media/AM3uUrlDialog.vue'
import AMediaDurationCheck from '@/components/media/AMediaDurationCheck.vue'
import AMediaSources from '@/components/media/AMediaSources.vue'
import APermissionGuard from '@/components/generic/APermissionGuard.vue'
import { useHasUserPermission } from '@/stores/auth'
import { MediaResolver, useMediaSourceController } from '@/stores/media-manager'
import AMediaSourceJobQueue from '@/components/media/AMediaSourceJobQueue.vue'
import { usePlayoutStore } from '@/stores'

const props = withDefaults(
  defineProps<{
    show: Show
    getMedia: MediaResolver
    disabled?: boolean
    media?: Media | null
    contextKey?: string | null | undefined
    requiredDurationSeconds?: number
  }>(),
  {
    requiredDurationSeconds: -1,
    contextKey: undefined,
    media: null,
  },
)

const attrs = useAttrs()
const { t } = useI18n()

const sources = computed(() => props.media?.entries ?? [])

const playoutStore = usePlayoutStore()
const mediaSourceManager = useMediaSourceController({
  show: () => props.show,
  contextKey: () => props.contextKey,
  getMedia: props.getMedia,
})

const isAllowedToAddFiles = useHasUserPermission(['program.add__file'])
function addFiles(files: File[] | FileList | null) {
  if (isAllowedToAddFiles.value) {
    mediaSourceManager.addFiles(files)
  }
}

// files handled through file dialog
const { open: openFileDialog, files } = useFileDialog({ accept: 'audio/*', multiple: true })
watch(files, (files) => addFiles(files))

// files handled through dropzone
const dropzoneEl = ref<HTMLDivElement>()
const { isOverDropZone, files: dropzoneFiles } = useDropZone(dropzoneEl)
watch(dropzoneFiles, (files) => addFiles(files))

// files imported by URL
const GetFileImportUrl = createTemplatePromise<string | null>()
async function importFileFromURL() {
  const fileUrl = await GetFileImportUrl.start()
  if (!fileUrl) return
  mediaSourceManager.addImports(fileUrl)
}

// streams
const GetStreamUrl = createTemplatePromise<string | null>()
async function addStreamMediaSource() {
  const streamURL = await GetStreamUrl.start()
  if (!streamURL) return
  mediaSourceManager.addUrls(streamURL)
}

// inputs
const GetInputUrl = createTemplatePromise<string | null>()
async function addInputMediaSource() {
  const url = await GetInputUrl.start()
  if (!url) return
  const input = playoutStore.inputs.find((input) => input.uri === url)
  const name = input?.label ?? t('input.singular')
  mediaSourceManager.addUrls({ url, name })
}

// M3U
const GetM3uUrl = createTemplatePromise<string | null>()
async function addM3UMediaSource() {
  const m3uUrl = await GetM3uUrl.start()
  if (!m3uUrl) return
  mediaSourceManager.addUrls(m3uUrl)
}
</script>