<template>
  <div>
    <CalendarHeaderComponent v-model="selectedDate" />
    <div class="boat-schedule-table-component">
      <QCalendarDay
        ref="calendar"
        class="q-pa-xs"
        flat
        animated
        dense
        :disabled-before="disabledBefore"
        interval-height="24"
        interval-count="18"
        interval-start="06:00"
        :short-interval-label="true"
        v-model="selectedDate"
        :column-count="boatData.length"
        @change="changeEvent"
        v-touch-swipe.left.right="handleSwipe"
      >
        <template #head-day="{ scope }">
          <div style="text-align: center; font-weight: 800">
            {{ getBoatDisplayName(scope) }}
          </div>
        </template>

        <template #day-body="{ scope }">
          <div v-for="block in getBoatBlocks(scope)" :key="block.$id">
            <div
              class="timeblock"
              :class="selectedBlock?.$id === block.$id ? 'selected' : ''"
              :style="
                blockStyles(block, scope.timeStartPos, scope.timeDurationHeight)
              "
              :id="block.id"
              @click="selectBlock($event, scope, block)"
            >
              {{ boatData[scope.columnIndex].name }}<br />
              {{ selectedBlock?.$id === block.$id ? 'Selected' : 'Available' }}
            </div>
          </div>
          <!-- <div
            v-for="r in boatData[scope.columnIndex].reservations"
            :key="r.id"
          >
            <div
              class="reservation"
              :style="
                reservationStyles(
                  r,
                  scope.timeStartPos,
                  scope.timeDurationHeight
                )
              "
            >
              {{ r.user }}
            </div>
          </div> -->
        </template>
      </QCalendarDay>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  QCalendarDay,
  Timestamp,
  diffTimestamp,
  today,
  parseTimestamp,
  parseDate,
  addToDate,
  makeDateTime,
} from '@quasar/quasar-ui-qcalendar';
import CalendarHeaderComponent from './CalendarHeaderComponent.vue';

import { ref, computed, onMounted } from 'vue';
import { Boat, useBoatStore } from 'src/stores/boat';
import { useScheduleStore } from 'src/stores/schedule';
import { Reservation, Timeblock } from 'src/stores/schedule.types';
import { date } from 'quasar';

const scheduleStore = useScheduleStore();
const boatStore = useBoatStore();
const boatData = boatStore.boats;
const selectedBlock = defineModel<Timeblock | null>();
const selectedDate = ref(today());

const calendar = ref<QCalendarDay | null>(null);

onMounted(async () => {
  await boatStore.fetchBoats();
  await scheduleStore.fetchTimeBlocks();
  //  useScheduleStore().fetchReservations()
}); // TODO: Probably need this to be more sophisticated.

function handleSwipe({ ...event }) {
  event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
}
function reservationStyles(
  reservation: Reservation,
  timeStartPos: (t: string) => string,
  timeDurationHeight: (d: number) => string
) {
  return genericBlockStyle(
    parseDate(reservation.start) as Timestamp,
    parseDate(reservation.end) as Timestamp,
    timeStartPos,
    timeDurationHeight
  );
}

function blockStyles(
  block: Timeblock,
  timeStartPos: (t: string) => string,
  timeDurationHeight: (d: number) => string
) {
  return genericBlockStyle(
    parseDate(new Date(block.start)) as Timestamp,
    parseDate(new Date(block.end)) as Timestamp,
    timeStartPos,
    timeDurationHeight
  );
}

function getBoatDisplayName(scope: DayBodyScope) {
  return boatData && boatData.value[scope.columnIndex]
    ? boatData.value[scope.columnIndex].displayName
    : '';
}

function genericBlockStyle(
  start: Timestamp,
  end: Timestamp,
  timeStartPos: (t: string) => string,
  timeDurationHeight: (d: number) => string
) {
  const s = {
    top: '',
    height: '',
    opacity: '',
  };
  if (timeStartPos && timeDurationHeight) {
    s.top = timeStartPos(start.time) + 'px';
    s.height =
      parseInt(
        timeDurationHeight(diffTimestamp(start, end, false) / 1000 / 60)
      ) -
      1 +
      'px';
  }
  // if (selectedBlock.value?.id === block.id) {
  //   s.opacity = '1.0';
  // }
  return s;
}

interface DayBodyScope {
  columnIndex: number;
  timeDurationHeight: string;
  timeStartPos: (time: string, clamp: boolean) => string;
  timestamp: Timestamp;
}

function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) {
  // TODO: Disable blocks before today with updateDisabled and/or comparison
  selectedBlock.value === block
    ? (selectedBlock.value = null)
    : (selectedBlock.value = block);
}

interface BoatBlocks {
  [key: string]: Timeblock[];
}

const boatBlocks = computed((): BoatBlocks => {
  return scheduleStore
    .getTimeblocksForDate(selectedDate.value)
    .reduce((result, tb) => {
      if (!result[tb.boatId]) result[tb.boatId] = [];
      result[tb.boatId].push(tb);
      return result;
    }, <BoatBlocks>{});
});

function getBoatBlocks(scope: DayBodyScope): Timeblock[] {
  return boatData.value[scope.columnIndex]
    ? boatBlocks.value[boatData.value[scope.columnIndex].$id]
    : [];
}

function changeEvent({ start }: { start: string }) {
  // const newBlocks = scheduleStore.getTimeblocksForDate(start);
  // const reservations = scheduleStore.getBoatReservations(
  //   parsed(start) as Timestamp
  // );
  // boatData.value.map((boat) => {
  //   boat.reservations = reservations.filter(
  //     (reservation) => reservation.resource === boat
  //   );
  //   boat.blocks = newBlocks.filter(
  //     (block) =>
  //       block.boatId === boat.$id &&
  //       boat.reservations?.filter(
  //         (r: Reservation) =>
  //           r.start <
  //             date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
  //               hours: 4,
  //             }) &&
  //           r.end >
  //             date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
  //               hours: 4,
  //             })
  //       ).length == 0
  //   );
  // });
  // setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout...
}

const disabledBefore = computed(() => {
  const todayTs = parseTimestamp(today()) as Timestamp;
  return addToDate(todayTs, { day: -1 }).date;
});
</script>

<style lang="sass">
.boat-schedule-table-component
  display: flex
  max-height: 60vh
  max-width: 98vw
.reservation
  display: flex
  position: absolute
  justify-content: center
  align-items: center
  text-align: center
  width: 100%
  opacity: 1
  margin: 0px
  text-overflow: ellipsis
  font-size: 0.8em
  cursor: pointer
  background: $accent
  color: white
  border: 1px solid black
.timeblock
  display: flex
  position: absolute
  justify-content: center
  text-align: center
  align-items: center
  width: 100%
  opacity: 0.5
  margin: 0px
  text-overflow: ellipsis
  font-size: 0.8em
  cursor: pointer
  background: $primary
  color: white
  border: 1px solid black
.selected
  opacity: 1 !important
.q-calendar-day__interval--text
  font-size: 0.8em
.q-calendar-day__day.q-current-day
  padding: 1px
</style>
