<template>
  <a
    v-if="!state.is_ready"
    :class="props.classes"
    @click="download_and_open()"
    title="T&#233;l&#233;charger"
  >
    <i class="fa fa-download"></i>
    <template v-if="displayActionStringInButton">Télécharger</template>
  </a>
  <a
    v-else
    :class="props.classes"
    target="_blank"
    :type="props.atVersion.type"
    :download="buildDocumentName()"
    :href="state.href_url"
    ref="open_button"
    title="Ouvrir"
  >
    <i class="fa fa-external-link"></i>
    <template v-if="displayActionStringInButton">Ouvrir</template>
  </a>
</template>

<script lang="ts" setup>
import { reactive, ref, nextTick, onMounted } from "vue";
import { download_and_decrypt_doc } from "./helpers";
import mime from "mime";
import { StoredObject, StoredObjectVersion } from "../../types";

interface DownloadButtonConfig {
  storedObject: StoredObject;
  atVersion: StoredObjectVersion;
  classes: Record<string, boolean>;
  filename?: string;
  /**
   * if true, display the action string into the button. If false, displays only
   * the icon
   */
  displayActionStringInButton?: boolean;
  /**
   * if true, will download directly the file on load
   */
  directDownload?: boolean;
}

interface DownloadButtonState {
  is_ready: boolean;
  is_running: boolean;
  href_url: string;
}

const props = withDefaults(defineProps<DownloadButtonConfig>(), {
  displayActionStringInButton: true,
  directDownload: false,
});
const state: DownloadButtonState = reactive({
  is_ready: false,
  is_running: false,
  href_url: "#",
});

const open_button = ref<HTMLAnchorElement | null>(null);

function buildDocumentName(): string {
  let document_name = props.filename ?? props.storedObject.title;

  if ("" === document_name || null === document_name) {
    document_name = "document";
  }

  const ext = mime.getExtension(props.atVersion.type);

  if (null !== ext) {
    return document_name + "." + ext;
  }

  return document_name;
}

async function download_and_open(): Promise<void> {
  if (state.is_running) {
    console.log("state is running, aborting");
    return;
  }

  state.is_running = true;

  if (state.is_ready) {
    console.log("state is ready. This should not happens");
    return;
  }

  let raw;

  try {
    raw = await download_and_decrypt_doc(props.storedObject, props.atVersion);
  } catch (e) {
    console.error("error while downloading and decrypting document");
    console.error(e);
    throw e;
  }

  state.href_url = window.URL.createObjectURL(raw);
  state.is_running = false;
  state.is_ready = true;

  if (!props.directDownload) {
    await nextTick();
    open_button.value?.click();

    console.log("open button should have been clicked");
    setTimeout(reset_state, 45000);
  }
}

function reset_state(): void {
  state.href_url = "#";
  state.is_ready = false;
  state.is_running = false;
}

onMounted(() => {
  if (props.directDownload) {
    download_and_open();
  }
});
</script>

<style scoped lang="scss">
i.fa::before {
  color: var(--bs-dropdown-link-hover-color);
}
i.fa {
  margin-right: 0.5rem;
}
</style>
