<template>
  <div
    v-if="tree !== null && fileId === null"
    class="w-100"
  >
    <CrudHeader title="Fichiers">
      <template #menu>
        <BButtonToolbar key-nav>
          <BButton
            variant="primary"
            class="me-2"
            @click="doAddFile"
            >+ fichier</BButton
          >
          <BButton
            variant="primary"
            @click="doAddDirectory"
            >+ Dossier</BButton
          >
        </BButtonToolbar>
      </template>
    </CrudHeader>

    <div
      v-if="!tree.is_root"
      class="p-3 border-bottom cursor"
      @click="cd(tree.parent)"
    >
      <span class="text-warning">
        <i class="fa-solid fa-folder me-2"></i>
      </span>
      ..
    </div>
    <div
      v-for="(item, key) in tree.directories"
      :key="key"
      class="p-3 border-bottom flex justify-content-center"
    >
      <div class="float-end">
        <BDropdown
          text=""
          size="sm"
          variant="outline-primary"
        >
          <BDropdownItem @click="doDelete(item)">Supprimer</BDropdownItem>
        </BDropdown>
      </div>
      <div
        class="cursor"
        @click="cd(item)"
      >
        <span class="text-warning cursor">
          <i class="fa-solid fa-folder me-2"></i>
        </span>
        {{ item.name }}
      </div>
    </div>
    <div
      v-for="item in tree.files"
      :key="item"
    >
      <div class="float-end pt-3 me-3">
        <BDropdown
          text=""
          size="sm"
          variant="outline-primary"
        >
          <BDropdownItem
            :href="`/api/filemanager/file/${item.id}/${item.name}`"
            target="_blank"
            >Télécharger</BDropdownItem
          >
          <BDropdownItem @click="doDelete(item)">Supprimer</BDropdownItem>
        </BDropdown>
      </div>
      <div
        v-if="isEditable(item)"
        class="p-3 border-bottom cursor"
        @click="doEdit(item)"
      >
        <span class="text-success">
          <i class="fa-solid fa-file-lines"></i>
        </span>
        {{ item.name }}
      </div>
      <div
        v-else
        class="p-3 border-bottom cursor"
      >
        <a
          :href="`/api/filemanager/file/${item.id}/${item.name}`"
          target="_blank"
        >
          <i class="fa-regular fa-file"></i>
          {{ item.name }}
        </a>
      </div>
    </div>
  </div>

  <div
    v-if="fileId !== null"
    class="w-100"
  >
    <div
      class="text-end cursor p-2 bg-secondary-subtle"
      @click="fileId = null"
    >
      <i class="fa-solid fa-xmark"></i>
    </div>
    <iframe
      id="collabora"
      title="Fichier"
      :src="'/collabora/' + fileId + '?extension=' + fileExtension"
    ></iframe>
  </div>

  <BModal
    v-if="form !== null"
    v-model="formShow"
    :title="form?.label"
    @ok="doSave"
  >
    <BAlert
      :model-value="form.error !== null"
      variant="danger"
      >{{ form.error }}</BAlert
    >
    <BForm @submit="doSave">
      <BFormGroup
        v-for="(field, key) in form.fields"
        :id="'form-label-' + key"
        :key="key"
        class="mb-2"
        :label="field.label"
        :label-for="'form-label-' + key"
        :description="field.description"
      >
        <BFormInput
          v-if="(field.widget ?? 'text') === 'text'"
          :id="'form-input-' + key"
          v-model="form.data[field.key]"
          :type="field.type"
          :required="field.required"
        />

        <BFormFile
          v-if="field.widget === 'file'"
          :id="'form-input-' + key"
          v-model="form.data[field.key]"
          :required="field.required"
        />

        <BFormSelect
          v-if="field.widget === 'select'"
          :id="'form-input-' + key"
          v-model="form.data[field.key]"
          :options="field.options"
          :required="field.required"
        />
      </BFormGroup>
    </BForm>
    <template #footer>
      <div></div>
      <div>
        <BButton
          variant="secondary"
          class="me-2"
          @click="formShow = false"
          >Annuler</BButton
        >
        <BButton
          variant="primary"
          @click="doSave"
          >OK</BButton
        >
      </div>
    </template>
  </BModal>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import CrudHeader from './../components/crud/CrudHeader.vue'
import { BModal, BButton, BForm, BFormGroup, BFormInput, BAlert, BFormSelect, BFormFile, BDropdown, BDropdownItem } from 'bootstrap-vue-next'
import { createRequestOptions } from '../lib/request'

let formFile = false
const tree = ref(null)
const fileId = ref(null)
const fileExtension = ref(null)
const form = ref(null)
const formShow = ref(false)
const cd = (directory) => {
  tree.value = directory
}
const doEdit = (item) => {
  fileId.value = item.id
  fileExtension.value = item.extension.replace(/^\./, '')
}

const withParents = (tree) => {
  tree.directories.forEach((subTree, key) => {
    tree.directories[key].parent = tree
    tree.directories[key] = withParents(tree.directories[key])
  })

  return tree
}

const isEditable = (item) => {
  return ['application/vnd.oasis.opendocument.spreadsheet', 'text/csv'].includes(item.type)
}

const doAddFile = () => {
  const data = { file: null }
  formFile = true

  form.value = {
    action: `/api/filemanager/file`,
    method: 'POST',
    data: data,
    label: 'Nouveau fichier',
    error: null,
    fields: [
      {
        label: 'Fichier',
        description: `Fichier ODT`,
        widget: 'file',
        required: true,
        key: 'file',
      },
    ],
  }

  formShow.value = true
}

const doAddDirectory = () => {
  const data = { directory: null, path: tree.value.id }
  formFile = false

  form.value = {
    action: `/api/filemanager/directory`,
    method: 'POST',
    data: data,
    label: 'Nouveau dossier',
    error: null,
    fields: [
      {
        label: 'Nom',
        widget: 'text',
        required: true,
        key: 'directory',
      },
    ],
  }

  formShow.value = true
}

const doDelete = (item) => {
  if (!confirm('Je confirme la suppression')) {
    return
  }

  fetch(
    `/api/filemanager/file/${item.id}`,
    createRequestOptions({
      method: 'DELETE',
    }),
  ).then(() => {
    refresh({ current: tree.value.id })
  })
}

const doSave = (e) => {
  e.preventDefault()

  if (formFile) {
    const payload = new FormData()
    payload.append('file', form.value.data.file)
    payload.append('path', tree.value.id)

    fetch(
      `/api/filemanager/file`,
      createRequestOptions({
        method: form.value.method,
        headers: {
          Accept: 'application/json',
        },
        body: payload,
      }),
    )
      .then((response) => {
        return response.json()
      })
      .then((data) => {
        if (data && data.code === 400) {
          form.value.error = data.message
        } else {
          form.value = null
          formShow.value = false
          refresh({ current: tree.value.id })
        }
      })
      .catch((err) => {
        form.value.error = `Une erreur s'est produite : ${err}`
      })
  } else {
    fetch(
      `/api/filemanager/directory`,
      createRequestOptions({
        method: form.value.method,
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(form.value.data),
      }),
    )
      .then((response) => {
        return response.json()
      })
      .then((data) => {
        if (data && data.code === 400) {
          form.value.error = data.message
        } else {
          form.value = null
          formShow.value = false
          refresh({ current: tree.value.id })
        }
      })
      .catch((err) => {
        form.value.error = `Une erreur s'est produite : ${err}`
      })
  }
}

const refresh = (options) => {
  options = options || {}

  fetch('/api/filemanager/files', createRequestOptions())
    .then((response) => response.json())
    .then((data) => {
      tree.value = withParents(data)

      if (options.current) {
        const tr = searchTree(options.current, data)

        if (tr) {
          cd(tr)
        }
      }
    })
}

const searchTree = (id, tree) => {
  if (tree.id === id) {
    return tree
  }

  for (let d of tree.directories) {
    const tr = searchTree(id, d)

    if (tr) {
      return tr
    }
  }

  return null
}

onMounted(() => refresh())
</script>

<style scoped>
a {
  text-decoration: none;
  color: var(--bs-body-color);
}
</style>
