<script setup>
import { computed, defineComponent } from "vue";
import { Effect } from "effect";
import { Icon } from "@iconify/vue";
import { ConfigProvider, TooltipProvider } from "reka-ui";
import { useI18n } from "vue-i18n";
import { Toaster } from "vue-sonner";
import ShwfedModal from "./modal.vue";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle
} from "./ui/alert-dialog";
import { Markdown } from "./ui/markdown";
import { useOverlay } from "../composables/useOverlay";
import { useHead } from "#app";
defineOptions({
  name: "ShwfedApp"
});
const overlay = useOverlay();
const { t } = useI18n({
  messages: {
    zh: { cancel: "\u53D6\u6D88", confirm: "\u786E\u8BA4" },
    en: { cancel: "Cancel", confirm: "Confirm" },
    ja: { cancel: "\u30AD\u30E3\u30F3\u30BB\u30EB", confirm: "\u78BA\u8A8D" },
    ko: { cancel: "\uCDE8\uC18C", confirm: "\uD655\uC778" }
  }
});
const OverlayBody = defineComponent({
  name: "OverlayBody",
  props: {
    render: {
      type: Function,
      required: true
    },
    slotProps: {
      type: Object,
      required: true
    }
  },
  setup(props) {
    return () => props.render(props.slotProps);
  }
});
const renderedSessions = computed(() => {
  const result = [];
  for (const session of overlay.sessions) {
    const definition = overlay.definitions[session.definitionId];
    if (!definition) {
      continue;
    }
    result.push({
      sessionId: session.sessionId,
      definitionId: session.definitionId,
      open: session.open,
      shell: {
        title: session.shell.title,
        description: session.shell.description,
        breakpoint: session.shell.breakpoint,
        trap: session.shell.trap,
        width: session.shell.width,
        descriptionSrOnly: session.shell.descriptionSrOnly
      },
      props: session.props,
      definition
    });
  }
  return result;
});
function handleOpenUpdate(sessionId, open) {
  if (open) {
    return;
  }
  Effect.runSync(overlay.close(sessionId));
}
function handleAfterClose(sessionId) {
  const finalizeClose = Reflect.get(overlay, "finalizeClose");
  if (typeof finalizeClose === "function") {
    finalizeClose(sessionId);
  }
}
function handleAlertConfirm(alertId) {
  Effect.runSync(overlay.closeAlert(alertId, true, true));
}
function handleAlertCancel(alertId) {
  Effect.runSync(overlay.closeAlert(alertId, false, true));
}
function handleAlertOpenUpdate(alertId, open) {
  if (open) {
    return;
  }
  Effect.runSync(overlay.closeAlert(alertId, false, false));
}
useHead({
  bodyAttrs: {
    style: {
      "--primary": "#2CA8BC"
    }
  }
});
</script>

<template>
  <ConfigProvider>
    <TooltipProvider :delay-duration="120">
      <slot />
      <Toaster />
      <ClientOnly>
        <template
          v-for="session in renderedSessions"
          :key="session.sessionId"
        >
          <ShwfedModal
            :open="session.open"
            :breakpoint="session.shell.breakpoint"
            :content-width="session.shell.width"
            :dismissible="!session.shell.trap"
            @update:open="handleOpenUpdate(session.sessionId, $event)"
            @after-close="handleAfterClose(session.sessionId)"
          >
            <template
              v-if="session.shell.title"
              #title
            >
              <Markdown :source="session.shell.title" />
            </template>

            <template
              v-if="session.shell.description"
              #description
            >
              <span
                v-if="session.shell.descriptionSrOnly"
                class="sr-only"
              >
                {{ session.shell.description }}
              </span>
              <template v-else>
                {{ session.shell.description }}
              </template>
            </template>

            <template #default="{ isDesktop }">
              <OverlayBody
                v-if="session.open"
                :render="session.definition.render"
                :slot-props="{
  props: session.props,
  report: (...args) => Effect.runSync(overlay.close(session.sessionId, ...args)),
  isDesktop
}"
              />
            </template>
          </ShwfedModal>
        </template>

        <template
          v-for="alert in overlay.alerts"
          :key="alert.alertId"
        >
          <AlertDialog
            :open="alert.open"
            @update:open="handleAlertOpenUpdate(alert.alertId, $event)"
          >
            <AlertDialogContent class="sm:px-12 sm:py-8 flex flex-col gap-12">
              <AlertDialogHeader class="sr-only">
                <AlertDialogTitle>Alert</AlertDialogTitle>
                <AlertDialogDescription>Confirmation dialog</AlertDialogDescription>
              </AlertDialogHeader>
              <Icon
                v-if="alert.icon"
                :icon="alert.icon"
                class="text-6xl mx-auto"
                :style="{ color: alert.color ?? '#000000' }"
              />
              <Markdown
                :source="alert.content"
                block
                class="prose prose-zinc text-sm"
              />
              <AlertDialogFooter>
                <AlertDialogCancel @click="handleAlertCancel(alert.alertId)">
                  <Icon icon="fluent:dismiss-20-regular" />
                  {{ t("cancel") }}
                </AlertDialogCancel>
                <AlertDialogAction @click="handleAlertConfirm(alert.alertId)">
                  <Icon icon="fluent:checkmark-20-regular" />
                  {{ t("confirm") }}
                </AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </template>
      </ClientOnly>
    </TooltipProvider>
  </ConfigProvider>
</template>
