<script setup lang="ts">
import type { BucketOut, BucketPermissionOut } from "@/client";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import PermissionModal from "@/components/object-storage/modals/PermissionModal.vue";
import BucketDetailModal from "@/components/object-storage/modals/BucketDetailModal.vue";
import dayjs from "dayjs";
import { computed, onMounted, reactive, ref } from "vue";
import { Toast, Tooltip } from "bootstrap";
import { useBucketStore } from "@/stores/buckets";
import { useRouter } from "vue-router";
import { useAuthStore } from "@/stores/users";
import type { FolderTree } from "@/types/PseudoFolder";
import { useNameStore } from "@/stores/names";
import { environment } from "@/environment";
import { useS3ObjectStore } from "@/stores/s3objects";
import { filesize } from "filesize";
import BootstrapToast from "@/components/BootstrapToast.vue";
import BucketLimitProgressBar from "@/components/object-storage/BucketLimitProgressBar.vue";

const props = defineProps<{
  active: boolean;
  bucket: BucketOut;
  loading: boolean;
  deletable: boolean;
}>();

const publicCheckbox = ref<HTMLInputElement | undefined>(undefined);
const randomIDSuffix = Math.random().toString(16).substring(2, 8);
const permissionRepository = useBucketStore();
const userRepository = useAuthStore();
const nameRepository = useNameStore();
const bucketRepository = useBucketStore();
const objectRepository = useS3ObjectStore();
const router = useRouter();

let successToast: Toast | null;
let errorToast: Toast | null;

const requestState = reactive<{
  error: string;
  loading: boolean;
}>({
  error: "",
  loading: false,
});

const permission = computed<BucketPermissionOut | undefined>(
  () => permissionRepository.ownPermissions[props.bucket.name],
);
const subFolder = computed<FolderTree>(() => {
  const subFolders: Record<string, FolderTree> = {};
  if (permission.value?.file_prefix != null) {
    subFolders[permission.value.file_prefix] = { subFolders: {}, files: [] };
  }
  return { subFolders: subFolders, files: [] };
});

const bucketMeta = computed<[number, number]>(() =>
  objectRepository.getMeta(props.bucket.name),
);

const emit = defineEmits<{
  (e: "delete-bucket", bucketName: string): void;
}>();

function permissionDeleted() {
  router.push({ name: "buckets" });
}

function toggleBucketPublicState() {
  requestState.loading = true;
  bucketRepository
    .updatePublicState(props.bucket.name, !props.bucket.public)
    .then(() => {
      successToast?.show();
    })
    .catch((err) => {
      requestState.error = err.toString();
      if (publicCheckbox.value) {
        publicCheckbox.value.checked = props.bucket.public;
      }
      errorToast?.show();
    })
    .finally(() => {
      requestState.loading = false;
    });
}

onMounted(() => {
  if (!props.loading) {
    new Tooltip("#tooltip-" + randomIDSuffix);
    new Tooltip(`#own-bucket-icon-${randomIDSuffix}`);
    new Tooltip(`#shared-bucket-icon-${randomIDSuffix}`);
    new Tooltip(`#public-bucket-icon-${randomIDSuffix}`);
    successToast = new Toast(`#success-public-bucket-${randomIDSuffix}`);
    errorToast = new Toast(`#error-public-bucket-${randomIDSuffix}`);
  }
});
</script>

<template>
  <bootstrap-toast
    :toast-id="`success-public-bucket-${randomIDSuffix}`"
    v-if="!loading"
  >
    Bucket {{ bucket.name }} is now {{ bucket.public ? "public" : "private" }}
  </bootstrap-toast>
  <bootstrap-toast
    :toast-id="`error-public-bucket-${randomIDSuffix}`"
    color-class="danger"
    v-if="!loading"
  >
    Error making the bucket {{ bucket.name }}
    {{ !bucket.public ? "public" : "private" }}:<br />
    {{ requestState.error }}
  </bootstrap-toast>
  <permission-modal
    v-if="permission != undefined && props.active"
    :modalId="'view-permission-modal' + randomIDSuffix"
    :bucket-name="props.bucket.name"
    :sub-folders="subFolder"
    :edit-user-permission="permission"
    :readonly="true"
    :editable="false"
    :deletable="true"
    :back-modal-id="undefined"
    @permission-deleted="permissionDeleted"
  />
  <bucket-detail-modal
    v-if="props.active"
    :modalId="`view-bucket-details-modal-${randomIDSuffix}`"
    :bucket="props.bucket"
    :edit-user-permission="permission"
  />
  <div class="mt-2 mb-2">
    <div
      v-if="loading"
      class="list-group-item list-group-item-action text-nowrap rounded"
    >
      <span class="placeholder w-75"></span>
    </div>
    <template v-else>
      <router-link
        class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"
        :class="{
          active: props.active,
          'hover-shadow': !props.active,
          rounded: !props.active,
          'rounded-top': props.active,
        }"
        :aria-current="props.active"
        :to="{
          name: 'bucket',
          params: { bucketName: bucket.name, subFolders: [] },
        }"
      >
        <span class="text-truncate flex-grow-3">
          {{ bucket.name }}
        </span>
        <div class="text-nowrap">
          <font-awesome-icon
            :hidden="!bucket.public"
            :id="`public-bucket-icon-${randomIDSuffix}`"
            icon="fa-solid fa-earth-americas"
            class="me-2"
            data-bs-toogle="tooltip"
            data-bs-title="Public Bucket"
          />
          <font-awesome-icon
            :hidden="bucket.owner_id !== userRepository.currentUID"
            :id="`own-bucket-icon-${randomIDSuffix}`"
            icon="fa-solid fa-user"
            :class="{
              'me-2':
                props.active ||
                permission ||
                (
                  permissionRepository.bucketPermissionsMapping[bucket.name] ??
                  []
                ).length > 0,
            }"
            data-bs-toogle="tooltip"
            data-bs-title="Own Bucket"
          />
          <font-awesome-icon
            :hidden="
              !permission &&
              (permissionRepository.bucketPermissionsMapping[bucket.name] ?? [])
                .length === 0
            "
            :id="`shared-bucket-icon-${randomIDSuffix}`"
            icon="fa-solid fa-users"
            :class="{ 'me-2': props.active }"
            data-bs-toogle="tooltip"
            data-bs-title="Shared Bucket"
          />
          <font-awesome-icon
            v-if="props.active && !permission && props.deletable"
            icon="fa-solid fa-trash"
            class="delete-icon me-2"
            @click="emit('delete-bucket', bucket.name)"
          />
          <font-awesome-icon
            class="info-icon"
            data-bs-toggle="modal"
            :data-bs-target="`#view-bucket-details-modal-${randomIDSuffix}`"
            v-if="props.active"
            icon="fa-solid fa-circle-info"
          />
        </div>
      </router-link>
      <div
        :hidden="!props.active"
        class="px-2 rounded-bottom border shadow-sm border-3 border-top-0 border-primary"
      >
        <div v-if="permission" class="ms-1 pt-1 text-info">Foreign Bucket</div>
        <table class="table table-sm table-borderless mb-0 align-middle">
          <tbody>
            <tr v-if="permission">
              <th scope="row" class="fw-bold">Permission:</th>
              <td>
                <a
                  href="#"
                  data-bs-toggle="modal"
                  :data-bs-target="'#view-permission-modal' + randomIDSuffix"
                  >Show</a
                >
              </td>
            </tr>
            <tr v-if="permission">
              <th scope="row" class="fw-bold">Owner:</th>
              <td class="text-truncate">
                {{ nameRepository.getName(bucket.owner_id) }}
              </td>
            </tr>
            <tr
              v-if="
                (
                  permissionRepository.bucketPermissionsMapping[bucket.name] ??
                  []
                ).length > 0
              "
            >
              <th scope="row" class="fw-bold">Permissions:</th>
              <td>
                <a
                  href="#"
                  data-bs-toggle="modal"
                  data-bs-target="#permission-list-modal"
                  >Show</a
                >
              </td>
            </tr>
            <tr>
              <th scope="row" class="fw-bold">Created:</th>
              <td>
                <span
                  :id="'tooltip-' + randomIDSuffix"
                  data-bs-toggle="tooltip"
                  :data-bs-title="
                    dayjs.unix(bucket.created_at).format('DD.MM.YYYY HH:mm:ss')
                  "
                >
                  {{ dayjs.unix(bucket.created_at).fromNow() }}
                </span>
              </td>
            </tr>
            <tr>
              <th scope="row" class="fw-bold">Objects:</th>
              <td v-if="bucket.object_limit">
                <bucket-limit-progress-bar
                  :maximum="bucket.object_limit"
                  :current-val="bucketMeta[0]"
                  :label="bucketMeta[0] + '/' + bucket.object_limit"
                />
              </td>
              <td v-else>{{ bucketMeta[0] }}</td>
            </tr>
            <tr>
              <th scope="row" class="fw-bold">Size:</th>
              <td v-if="bucket.size_limit">
                <bucket-limit-progress-bar
                  :maximum="1024 * bucket.size_limit"
                  :current-val="bucketMeta[1]"
                  :label="
                    filesize(bucketMeta[1]) +
                    '/' +
                    filesize(1024 * bucket.size_limit)
                  "
                />
              </td>
              <td v-else>{{ filesize(bucketMeta[1]) }}</td>
            </tr>
            <tr>
              <th scope="row">
                <div
                  :class="{ 'form-check': !loading && permission == undefined }"
                >
                  <input
                    v-if="!loading && permission == undefined"
                    ref="publicCheckbox"
                    class="form-check-input"
                    type="checkbox"
                    :disabled="requestState.loading"
                    :checked="bucket.public"
                    :id="'public-checkbox-' + randomIDSuffix"
                    @change="toggleBucketPublicState"
                  />
                  <label
                    :for="'public-checkbox-' + randomIDSuffix"
                    class="fw-bold"
                  >
                    Public</label
                  >
                </div>
              </th>
              <td>
                <a
                  v-if="bucket.public"
                  target="_blank"
                  :href="environment.S3_URL + '/' + bucket.name"
                  >Link</a
                >
                <span v-else>Disabled</span>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </template>
  </div>
</template>

<style scoped>
.delete-icon {
  color: white;
}

.delete-icon:hover {
  color: var(--bs-danger) !important;
}

.info-icon {
  color: white;
}

.info-icon:hover {
  color: var(--bs-info) !important;
}
</style>