<!--
Wrapper to allow an UI element to trigger a file download

The only required property is the File entity to download. It has to be in READY state.
Trigger the download by calling `scope.download` on the event you like.
If you want to display a loading animation while the download request is submitted, you can achieve this with `scope.downloading`

Usage (default button) :

    <UiDownloader :file="file"></UiDownloader>

Usage (custom button) :

    <UiDownloader :file="file" v-slot="scope">
        <v-btn color="primary" :loading="scope.downloading" @click="scope.download">
            {{ $t('download') }}
        </v-btn>
    </UiDownloader>
-->

<template>
  <div>
    <slot :download="download" :downloading="downloading">
      <v-btn :loading="downloading" :disabled="downloading" @click="download">
        {{ $t('download') }}
      </v-btn>
    </slot>
  </div>
</template>

<script lang="ts">

import {defineComponent, ref, Ref, useContext} from "@nuxtjs/composition-api";
import {QUERY_TYPE} from "~/types/enums";
import {DataProviderArgs} from "~/types/interfaces";
import {File} from "~/models/Core/File";
import {Bool} from "@vuex-orm/core";

export default defineComponent({
  props: {
    file: {
      type: File,
      required: true
    },
    target: {
      type: String,
      required: false,
      default: '_blank'
    }
  },
  setup (props) {

    const { $dataProvider } = useContext()

    let { file, target } = props
    let downloading: Ref<Boolean> = ref(false)

    const download = async () => {
      if (!file) {
        console.error("File is not defined yet, impossible to download")
        return
      }
      if (file.status === 'PENDING') {
        console.error("File is not ready yet, impossible to download")
        return
      }
      if (file.status === 'ERROR') {
        console.error("An error occurred wilie generating the file, impossible to download")
        return
      }
      if (file.status !== 'READY') {
        console.error("File status is not correctly defined")
        return
      }
      if (downloading.value) {
        console.error("A download request is already being processed")
        return
      }

      downloading.value = true

      const response = await $dataProvider.invoke(
        {
          type: QUERY_TYPE.FILE,
          fileArgs: { fileId: file.id }
        } as DataProviderArgs
      )

      downloading.value = false

      const blob = new Blob([response.data], { type: response.data.type })

      const url = window.URL.createObjectURL(blob)

      const link = document.createElement('a')
      link.href = url
      link.download = file.name ?? 'document'
      link.target = target
      link.click()

      link.remove()
      window.URL.revokeObjectURL(url)

    }

    return {
      download: () => download(),
      downloading
    }
  }
})
</script>
