import { computed, shallowRef, type ComputedRef, watch } from 'vue';
import { add, sub, cmp, time, type Time } from '@silane/datetime';

import { comparerByKey, groupBy } from '../../../../../../common/utils';
import type { TimeLabel } from '../../../../../../composables/timelabelstore';
import type { Event } from '../../../../../../composables/eventstore';


function roundTime(t: Time) {
  return time(t.hour, t.minute - t.minute % 5, 0, 0, t.tzInfo, t.fold);
}

export function useTimetableCursor(
  relatedEvent: ComputedRef<Event | null>,
  timeLabels: ComputedRef<TimeLabel[]>,
) {
  const timeLabelGroups = computed(() => groupBy(
    timeLabels.value, x => sub(x.endTime, x.startTime),
    (a, b) => cmp(a, b) === 0,
  ).map(x => x.items));

  const rawCurrentPosition = shallowRef<{
    columnID: string, time: Time,
  } | null>(null);

  function timelineMouseEventHandler(eventType, details: {
    columnID: string, time: Time,
  }) {
    rawCurrentPosition.value = { ...details };
  }

  const cursor = computed(() => {
    if(!relatedEvent.value || !rawCurrentPosition.value) return null;

    if(relatedEvent.value.timeLabel) {
      const group = timeLabelGroups.value.find(x => x.some(
        tl => tl.id === relatedEvent.value!.timeLabel!.id
      ))!;
      const tl = group.find(x => cmp(
        x.startTime, rawCurrentPosition.value!.time
      ) <= 0 && cmp(rawCurrentPosition.value!.time, x.endTime) <= 0);
      if(tl) {
        return {
          columnID: rawCurrentPosition.value.columnID,
          startTime: tl.startTime, endTime: tl.endTime, timeLabel: tl,
        };
      } else {
        return null;
      }
    } else {
      const startTime = roundTime(rawCurrentPosition.value.time);
      return {
        columnID: rawCurrentPosition.value.columnID, startTime, endTime: add(
          startTime, sub(
            relatedEvent.value.endTime, relatedEvent.value.startTime
          ),
        ), timeLabel: null,
      };
    }
  });

  const cursorCached = shallowRef<typeof cursor.value>(null);
  watch(cursor, () => {
    if(comparerByKey<typeof cursor.value>(x => x == null ? [] : [
      x.columnID, x.startTime.isoFormat(), x.endTime.isoFormat(),
      x.timeLabel?.id ?? '',
    ])(cursor.value, cursorCached.value) !== 0) {
      cursorCached.value = cursor.value;
    }
  }, { immediate: true });

  return { cursor: cursorCached, timelineMouseEventHandler };
}
