<script setup lang="ts">
import { computed, onBeforeUnmount, reactive, watch } from "vue";
import { Check, Close, CopyDocument, InfoFilled, WarningFilled } from "@element-plus/icons-vue";
import { useToastStore, type ToastItem } from "@/stores/toast";

const store = useToastStore();
const elapsed = reactive<Record<number, number>>({});
const paused = reactive<Record<number, boolean>>({});
let lastTick = performance.now();
const timer = window.setInterval(() => {
  const now = performance.now();
  const delta = now - lastTick;
  lastTick = now;
  for (const item of store.visible) {
    if (!paused[item.id]) elapsed[item.id] = (elapsed[item.id] || 0) + delta;
    if (elapsed[item.id] >= item.duration) store.remove(item.id);
  }
}, 50);

watch(
  () => store.visible.map((item) => item.id),
  (ids) => {
    ids.forEach((id) => {
      if (elapsed[id] === undefined) elapsed[id] = 0;
    });
  },
);
onBeforeUnmount(() => window.clearInterval(timer));

const icons = { success: Check, warning: WarningFilled, error: WarningFilled, info: InfoFilled };
const progress = (item: ToastItem) =>
  computed(() => Math.max(0, 100 - ((elapsed[item.id] || 0) / item.duration) * 100)).value;
async function copy(item: ToastItem) {
  await navigator.clipboard.writeText(item.copyText || item.message);
}
</script>

<template>
  <div class="toast-region">
    <TransitionGroup name="toast-fade">
      <section
        v-for="item in store.visible"
        :key="item.id"
        class="app-toast"
        :class="`app-toast--${item.type}`"
        @mouseenter="paused[item.id] = true"
        @mouseleave="paused[item.id] = false"
      >
        <el-icon class="app-toast__icon"><component :is="icons[item.type]" /></el-icon>
        <div class="app-toast__content">
          <strong>{{ item.title }}</strong>
          <span>{{ item.message }}</span>
        </div>
        <button
          v-if="item.type === 'error'"
          class="icon-button"
          type="button"
          title="复制完整错误"
          @click="copy(item)"
        >
          <el-icon><CopyDocument /></el-icon>
        </button>
        <button
          class="icon-button"
          type="button"
          title="关闭提示"
          @click="store.remove(item.id)"
        >
          <el-icon><Close /></el-icon>
        </button>
        <div
          class="app-toast__progress"
          :style="{ width: `${progress(item)}%` }"
        />
      </section>
    </TransitionGroup>
  </div>
</template>
