<template>
  <q-dialog
    :model-value="editor !== undefined"
    persistent
    transition-show="scale"
    transition-hide="scale"
  >
    <q-card>
      <div class="column">
        <div class="col" align="right" style="position: sticky; top: 0; z-index: 999">
          <q-btn round color="negative" icon="mdi-close" dense rounded @click="editDone(false)" />
        </div>
        <div class="col" style="margin: 0; padding: 0; margin-top: -2.4em">
          <edit-event v-model="editor" @done="editDone" />
        </div>
      </div>
    </q-card>
  </q-dialog>
  <q-card>
    <div style="max-width: 1800px; width: 100%">
      <div class="bg-primary text-white q-my-sm shadow-2 row justify-center">
        <div class="col-xs-12 col-sm-9 row justify-center items-center">
          <q-btn flat dense icon="mdi-chevron-left" title="previous" @click="calendarPrev" />
          <q-separator vertical />
          <q-btn flat dense
            >{{ asMonth(selectedDate) }} {{ asYear(selectedDate) }}
            <q-popup-proxy ref="proxy" transition-show="scale" transition-hide="scale">
              <q-date
                ref="datepicker"
                :model-value="selectedDate"
                mask="YYYY-MM-DD"
                no-unset
                @update:model-value="updateDate"
                ><q-btn v-close-popup label="jetzt" dense flat @click="datepicker?.setToday()"
              /></q-date>
            </q-popup-proxy>
          </q-btn>
          <q-separator vertical />
          <q-btn flat dense icon="mdi-chevron-right" title="next" @click="calendarNext" />
        </div>
        <div class="col-xs-12 col-sm-3 text-center">
          <q-btn-toggle
            v-if="$q.screen.gt.xs"
            v-model="calendarView"
            flat
            stretch
            toggle-color="black"
            :options="[
              { label: 'Tag', value: 'day' },
              { label: 'Woche', value: 'week' },
            ]"
          />
        </div>
      </div>
      <q-calendar-agenda
        v-model="selectedDate"
        :view="calendarRealView"
        :max-days="calendarDays"
        :weekdays="[1, 2, 3, 4, 5, 6, 0]"
        locale="de-de"
        style="height: 100%; min-height: 400px"
      >
        <template #head-day-label="{ scope: { timestamp } }">
          {{ timestamp.day }}
          <q-menu>
            <q-list style="min-width: 100px">
              <q-item exact clickable @click="create(timestamp.date)">
                <q-item-section>Neue Veranstaltung</q-item-section>
              </q-item>
            </q-list>
          </q-menu>
        </template>
        <template #day="{ scope: { timestamp } }">
          <div itemref="" class="q-pa-sm" style="min-height: 200px">
            <event-slot
              v-for="(agenda, index) in events[timestamp.weekday]"
              :key="index"
              v-model="events[timestamp.weekday][index]"
              class="q-mb-sm"
              @remove-event="remove"
              @edit-event="edit"
            />
          </div>
        </template>
      </q-calendar-agenda>
    </div>
  </q-card>
</template>

<script lang="ts">
import { ComponentPublicInstance, computed, defineComponent, onBeforeMount, ref } from 'vue';
import { useEventStore } from '../../store';
import EventSlot from './slots/EventSlot.vue';
import { date, QDate, QPopupProxy, useQuasar } from 'quasar';
import { startOfWeek } from '@flaschengeist/api';
import EditEvent from '../management/EditEvent.vue';
import { QCalendarAgenda } from '@quasar/quasar-ui-qcalendar';
import { EditableEvent, emptyEvent } from '../../store/models';

export default defineComponent({
  name: 'AgendaView',
  components: { EventSlot, EditEvent, QCalendarAgenda: <ComponentPublicInstance>QCalendarAgenda },

  setup() {
    const store = useEventStore();
    const quasar = useQuasar();

    const datepicker = ref<QDate>();
    const proxy = ref<QPopupProxy>();

    const selectedDate = ref(date.formatDate(new Date(), 'YYYY-MM-DD'));
    const calendarView = ref('week');

    const calendarRealView = computed(() => (calendarDays.value != 7 ? 'day' : 'week'));
    const calendarDays = computed(() =>
      calendarView.value == 'day' || quasar.screen.xs ? 1 : quasar.screen.sm ? 3 : 7
    );
    const events = ref<Agendas>({});
    const editor = ref<EditableEvent>();

    interface Agendas {
      [index: number]: FG.Event[];
    }

    onBeforeMount(async () => {
      await loadAgendas();
    });

    function create(ds: string) {
      editor.value = emptyEvent(date.extractDate(ds, 'YYYY-MM-DD'));
    }
    async function edit(id: number) {
      editor.value = await store.getEvent(id);
    }
    function editDone(changed: boolean) {
      if (changed) void loadAgendas();
      editor.value = undefined;
    }

    async function remove(id: number) {
      if (await store.removeEvent(id)) {
        // Successfull removed
        for (const idx in events.value) {
          const i = events.value[idx].findIndex((event) => event.id === id);
          if (i !== -1) {
            events.value[idx].splice(i, 1);
            break;
          }
        }
      } else {
        // Not found, this means our eventa are outdated
        await loadAgendas();
      }
    }

    async function loadAgendas() {
      const selected = date.adjustDate(selectedDate.value, {
        milliseconds: 0,
        seconds: 0,
        minutes: 0,
        hours: 0,
      });
      const start = calendarRealView.value === 'day' ? selected : startOfWeek(selected);
      const end = date.addToDate(start, { days: calendarDays.value });

      events.value = {};
      const list = await store.getEvents({ from: start, to: end });
      list.forEach((event) => {
        const day = event.start.getDay();

        if (!events.value[day]) {
          events.value[day] = [];
        }
        events.value[day].push(event);
      });
    }

    function calendarNext() {
      selectedDate.value = date.formatDate(
        date.addToDate(selectedDate.value, { days: calendarDays.value }),
        'YYYY-MM-DD'
      );
      void loadAgendas();
    }

    function calendarPrev() {
      selectedDate.value = date.formatDate(
        date.subtractFromDate(selectedDate.value, { days: calendarDays.value }),
        'YYYY-MM-DD'
      );
      void loadAgendas();
    }

    function asMonth(value: string) {
      if (value) {
        return date.formatDate(new Date(value), 'MMMM', {
          months: [
            'Januar',
            'Februar',
            'März',
            'April',
            'Mai',
            'Juni',
            'Juli',
            'August',
            'September',
            'Oktober',
            'November',
            'Dezember',
          ],
        });
      }
    }
    function asYear(value: string) {
      if (value) {
        return date.formatDate(new Date(value), 'YYYY');
      }
    }

    return {
      asYear,
      asMonth,
      calendarDays,
      calendarNext,
      calendarPrev,
      calendarRealView,
      calendarView,
      create,
      edit,
      editor,
      editDone,
      events,
      datepicker,
      proxy,
      remove,
      selectedDate,
      updateDate: (ds: string) => {
        selectedDate.value = ds;
        proxy.value?.hide();
      },
    };
  },
});
</script>

<style>
@import '@quasar/quasar-ui-qcalendar/dist/index.css';

/* Fill full height of card */
.q-calendar-agenda__pane {
  height: 100%;
}

/* Same as Qcard */
.q-calendar {
  --calendar-background-dark: --q-dark;
}
</style>
