<template>
  <div class="flex flex-col w-full h-full gap-2 justify-between overflow-hidden">
    <div class="flex flex-row gap-2 max-xl:flex-wrap justify-between max-sm:justify-center">
      <div class="flex flex-row max-xl:order-2">
        <button
          :primary="view == 'dayGridMonth'"
          :primary-outline="view != 'dayGridMonth'"
          class="rounded-r-none!"
          @click="setView('dayGridMonth')"
        >
          Monat
        </button>
        <button
          :primary="view == 'timeGridWeek'"
          :primary-outline="view != 'timeGridWeek'"
          class="rounded-none! border-x-0!"
          @click="setView('timeGridWeek')"
        >
          Woche
        </button>
        <button
          :primary="view == 'listMonth'"
          :primary-outline="view != 'listMonth'"
          class="rounded-l-none!"
          @click="setView('listMonth')"
        >
          Liste
        </button>
      </div>
      <p class="text-3xl w-full max-xl:order-1 text-center">{{ currentTitle }}</p>
      <div class="flex flex-row max-xl:order-3">
        <button primary-outline class="rounded-r-none!" @click="navigateView('prev')">
          <ChevronLeftIcon />
        </button>
        <button
          :primary="containsToday"
          :primary-outline="!containsToday"
          class="rounded-none! border-x-0!"
          @click="
            calendarApi?.today();
            containsToday = true;
          "
        >
          heute
        </button>
        <button primary-outline class="rounded-l-none!" @click="navigateView('next')">
          <ChevronRightIcon />
        </button>
      </div>
    </div>
    <FullCalendar ref="fullCalendar" :options="calendarOptions" class="max-h-full h-full" />
  </div>
</template>

<script setup lang="ts">
import { defineComponent, type PropType } from "vue";
import FullCalendar from "@fullcalendar/vue3";
import deLocale from "@fullcalendar/core/locales/de";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin from "@fullcalendar/interaction";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/vue/24/outline";
import type { CalendarOptions } from "@fullcalendar/core/index.js";
</script>

<script lang="ts">
export default defineComponent({
  props: {
    items: {
      type: Array as PropType<
        {
          id: string;
          title: string;
          start: string;
          end: string;
          backgroundColor: string;
        }[]
      >,
      default: [],
    },
    allowInteraction: {
      type: Boolean,
      default: true,
    },
  },
  emits: {
    dateSelect: ({ start, end, allDay }: { start: string; end: string; allDay: boolean }) => {
      return typeof start == "string" && typeof end == "string" && typeof allDay === "boolean";
    },
    eventSelect: (id: string) => {
      return typeof id == "string";
    },
  },
  data() {
    return {
      view: "dayGridMonth" as "dayGridMonth" | "timeGridWeek" | "listMonth",
      calendarApi: null as null | typeof FullCalendar,
      currentTitle: "" as string,
      containsToday: false as boolean,
    };
  },
  computed: {
    calendarOptions() {
      return {
        timeZone: "local",
        locale: deLocale,
        plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin],
        initialView: "dayGridMonth",
        eventDisplay: "block",
        headerToolbar: false,
        weekends: true,
        editable: this.allowInteraction,
        selectable: this.allowInteraction,
        selectMirror: false,
        dayMaxEvents: true,
        weekNumbers: true,
        displayEventTime: true,
        nowIndicator: true,
        weekText: "KW",
        allDaySlot: false,
        events: this.items,
        select: this.select,
        eventClick: this.eventClick,
      } as CalendarOptions;
    },
  },
  mounted() {
    this.calendarApi = (this.$refs.fullCalendar as typeof FullCalendar).getApi();
    this.setTitle();
    this.setContainsToday();
  },
  methods: {
    setTitle() {
      this.currentTitle = this.calendarApi?.view.title ?? "";
    },
    setView(view: "dayGridMonth" | "timeGridWeek" | "listMonth") {
      this.calendarApi?.changeView(view);
      this.view = view;
      this.setTitle();
      this.setContainsToday();
    },
    navigateView(change: "prev" | "next") {
      if (change == "prev") {
        this.calendarApi?.prev();
      } else {
        this.calendarApi?.next();
      }
      this.setTitle();
      this.setContainsToday();
    },
    setContainsToday() {
      const start = this.calendarApi?.view.currentStart;
      const end = this.calendarApi?.view.currentEnd;
      const today = new Date();
      this.containsToday = today >= start && today < end;
    },
    select(e: any) {
      this.$emit("dateSelect", {
        start: e?.startStr ?? new Date().toISOString(),
        end: e?.endStr ?? new Date().toISOString(),
        allDay: e?.allDay ?? false,
      });
    },
    eventClick(e: any) {
      this.$emit("eventSelect", e.event.id);
    },
  },
});
</script>
