<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref, useId, watch } from "vue";
import DsIconButton from "../actions/DsIconButton.vue";

const props = withDefaults(
  defineProps<{
    title: string;
    description?: string;
    closeLabel?: string;
    closeOnBackdrop?: boolean;
  }>(),
  {
    description: undefined,
    closeLabel: "Cerrar diálogo",
    closeOnBackdrop: true,
  },
);
const model = defineModel<boolean>({ default: false });
const emit = defineEmits<{ close: []; cancel: [] }>();
const dialog = ref<HTMLDialogElement | null>(null);
const titleId = useId();
const descriptionId = useId();
let previousFocus: HTMLElement | null = null;

async function syncDialog(open: boolean) {
  await nextTick();
  if (open && dialog.value && !dialog.value.open) {
    previousFocus = document.activeElement as HTMLElement | null;
    dialog.value.showModal();
  } else if (!open && dialog.value?.open) {
    dialog.value.close();
    previousFocus?.focus();
  }
}

watch(model, syncDialog);
onMounted(() => syncDialog(model.value));

function requestClose(cancelled = false) {
  model.value = false;
  if (cancelled) emit("cancel");
  emit("close");
}

function onCancel(event: Event) {
  event.preventDefault();
  requestClose(true);
}

function onBackdrop(event: MouseEvent) {
  if (props.closeOnBackdrop && event.target === dialog.value)
    requestClose(true);
}

onBeforeUnmount(() => {
  if (dialog.value?.open) dialog.value.close();
});
</script>

<template>
  <dialog
    ref="dialog"
    class="ds-dialog"
    :aria-labelledby="titleId"
    :aria-describedby="description ? descriptionId : undefined"
    @cancel="onCancel"
    @click="onBackdrop"
  >
    <div class="ds-dialog__header">
      <div>
        <h2 :id="titleId" class="ds-dialog__title">{{ title }}</h2>
        <p
          v-if="description"
          :id="descriptionId"
          class="ds-dialog__description"
        >
          {{ description }}
        </p>
      </div>
      <DsIconButton :label="closeLabel" @click="requestClose(true)"
        >×</DsIconButton
      >
    </div>
    <div class="ds-dialog__body"><slot /></div>
    <footer v-if="$slots.footer" class="ds-dialog__footer">
      <slot name="footer" :close="requestClose" />
    </footer>
  </dialog>
</template>
