<template>
  <div
    class="fixed right-0 flex flex-col gap-4 p-2 w-full md:w-80 z-50"
    :class="position == 'bottom' ? 'bottom-0' : 'top-0'"
  >
    <TransitionGroup
      :enter-active-class="notifications.length > 1 ? [props.enter, props.moveDelay].join(' ') : props.enter"
      :enter-from-class="props.enterFrom"
      :enter-to-class="props.enterTo"
      :leave-active-class="props.leave"
      :leave-from-class="props.leaveFrom"
      :leave-to-class="props.leaveTo"
      :move-class="props.move"
    >
      <div
        v-for="notification in sortedNotifications"
        :key="notification.id"
        class="relative p-2 bg-white flex flex-row gap-2 w-full overflow-hidden rounded-lg shadow-md"
        :class="[
          notification.type == 'error' ? 'border border-red-400' : '',
          notification.type == 'warning' ? 'border border-red-400' : '',
          notification.type == 'info' ? 'border border-gray-400' : '',
        ]"
      >
        <!-- @mouseover="hovering(notification.id, true)"
        @mouseleave="hovering(notification.id, false)" -->
        <ExclamationCircleIcon
          v-if="notification.type == 'error'"
          class="flex items-center justify-center min-w-12 w-12 h-12 bg-red-500 rounded-lg text-white p-1"
        />
        <ExclamationTriangleIcon
          v-if="notification.type == 'warning'"
          class="flex items-center justify-center min-w-12 w-12 h-12 bg-red-500 rounded-lg text-white p-1"
        />
        <InformationCircleIcon
          v-if="notification.type == 'info'"
          class="flex items-center justify-center min-w-12 w-12 h-12 bg-gray-500 rounded-lg text-white p-1"
        />

        <div class="flex flex-col">
          <span
            class="font-semibold"
            :class="[
              notification.type == 'error' ? 'text-red-500' : '',
              notification.type == 'warning' ? 'text-red-500' : '',
              notification.type == 'info' ? 'text-gray-700' : '',
            ]"
            >{{ notification.title }}</span
          >
          <p class="text-sm text-gray-600">{{ notification.text }}</p>
        </div>
        <XMarkIcon
          @click="close(notification.id)"
          class="absolute top-2 right-2 w-6 h-6 cursor-pointer text-gray-500"
        />
        <div
          class="absolute left-0 bottom-0 h-1 bg-gray-500 transition-[width] duration-[4900ms] ease-linear"
          :class="notification.indicator ? 'w-0' : 'w-full'"
        ></div>
      </div>
    </TransitionGroup>
  </div>
</template>

<script setup lang="ts">
import { defineComponent, TransitionGroup } from "vue";
import { mapState, mapActions } from "pinia";
import { useNotificationStore } from "@/stores/notification";
import {
  ExclamationTriangleIcon,
  ExclamationCircleIcon,
  InformationCircleIcon,
  XMarkIcon,
} from "@heroicons/vue/24/outline";

export interface Props {
  maxNotifications?: number;
  enter?: string;
  enterFrom?: string;
  enterTo?: string;
  leave?: string;
  leaveFrom?: string;
  leaveTo?: string;
  move?: string;
  moveDelay?: string;
  position?: string;
}

const props = withDefaults(defineProps<Props>(), {
  maxNotifications: 10,
  enter: "transform ease-out duration-300 transition",
  enterFrom: "translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4",
  enterTo: "translate-y-0 opacity-100 sm:translate-x-0",
  leave: "transition ease-in duration-500",
  leaveFrom: "opacity-100",
  leaveTo: "opacity-0",
  move: "transition duration-500",
  moveDelay: "delay-300",
  position: "bottom",
});
</script>

<script lang="ts">
export default defineComponent({
  computed: {
    ...mapState(useNotificationStore, ["notifications", "timeouts"]),
    sortedNotifications() {
      if (this.position === "bottom") {
        return [...this.notifications];
      }
      return [...this.notifications].reverse();
    },
  },
  methods: {
    ...mapActions(useNotificationStore, ["revoke"]),
    close(id: string) {
      this.revoke(id);
    },
    hovering(id: string, value: boolean, timeout?: number) {
      if (value) {
        clearTimeout(this.timeouts[id]);
      } else {
        this.timeouts[id] = setTimeout(() => {
          this.revoke(id);
        }, timeout);
      }
    },
  },
});
</script>
