import { getTimeIndex } from '../../../utils';
/** The VegaCalendarEventSorter class in TypeScript provides a sort method to sort an array of CalendarEvent objects. */
export class VegaCalendarEventSorter {
  /**
   * The function "sort" takes an array of CalendarEvent objects and returns the same array without performing any sorting.
   *
   * @param {CalendarEvent[]} events - CalendarEvent[] - an array of CalendarEvent objects that need to be sorted.
   * @param {number} currentViewIndex - The current index of the row
   * @param {VegaCalendarFullDayEventLayout} fullDayEventLayout - The current row all long event layout
   * @returns {Nullable<CalendarEvent>[]} The `sort` function is currently returning the input array of `CalendarEvent` objects as is, without performing any sorting operation.
   */
  sort(events, currentViewIndex, fullDayEventLayout) {
    const allDayEvents = [];
    const groupEvents = [];
    const otherEvents = [];
    for (let i = 0; i < events.length; i++) {
      const currentEvent = events[i];
      if (currentEvent) {
        if (currentEvent.isGroupEvent()) {
          groupEvents.push(currentEvent);
        }
        else if (currentEvent.isAllDayEvent) {
          allDayEvents.push(currentEvent);
        }
        else {
          otherEvents.push(currentEvent);
        }
      }
    }
    let result = allDayEvents.concat(this.sortCalendarEventByTime(otherEvents));
    let currentViewOrderGroupEvents = fullDayEventLayout.getEventsByIndex(currentViewIndex);
    const currentEvents = currentViewOrderGroupEvents.filter((item) => item);
    result = groupEvents
      .filter((groupEvent) => {
      return currentEvents.findIndex((item) => item === groupEvent) < 0;
    })
      .concat(result);
    if (currentViewOrderGroupEvents.length > currentEvents.length) {
      const insertItems = result.slice(0, currentViewOrderGroupEvents.length - currentEvents.length);
      result = result.slice(currentViewOrderGroupEvents.length - currentEvents.length);
      currentViewOrderGroupEvents = this.insertEventsToEmptyPosition(currentViewOrderGroupEvents, insertItems);
    }
    result = currentViewOrderGroupEvents.concat(result);
    return result;
  }
  /**
   * The function `sortCalendarEventByTime` sorts an array of `CalendarEvent` objects based on their start and end times.
   *
   * @param {CalendarEvent[]} events - An array of CalendarEvent objects. Each CalendarEvent object contains information about a specific event, such as startTime and endTime.
   * @returns {CalendarEvent[]} The `sortCalendarEventByTime` function is returning an array of `CalendarEvent` objects sorted by their start time and end time. The events are sorted in ascending order based on their start time, and if two events have the same start time, they are further sorted in descending order based on their end time.
   */
  sortCalendarEventByTime(events) {
    return events.sort((eventA, eventB) => {
      const eventAStartIndex = getTimeIndex(eventA.startTime.toString());
      const eventBStartIndex = getTimeIndex(eventB.startTime.toString());
      if (eventAStartIndex === eventBStartIndex) {
        return getTimeIndex(eventB.endTime.toString()) - getTimeIndex(eventA.endTime.toString());
      }
      else {
        return eventAStartIndex - eventBStartIndex;
      }
    });
  }
  /**
   * The function inserts events from a given array into empty positions in another array of events.
   *
   * @param {Nullable<CalendarEvent>[]} viewEvents - `viewEvents` is an array of nullable
   * `CalendarEvent` objects representing the events currently displayed in the calendar view. Each
   * element in the array can either be a `CalendarEvent` object or `null`.
   * @param {CalendarEvent[]} events - The `events` parameter in the `insertEventsToEmptyPosition`
   * function represents an array of `CalendarEvent` objects that need to be inserted into the
   * `viewEvents` array at empty positions. The function iterates over the `viewEvents` array and
   * inserts events from the `events` array
   * @returns {Nullable<CalendarEvent>[]} The `insertEventsToEmptyPosition` function returns an array of `Nullable<CalendarEvent>`
   * where events from the `events` array are inserted into empty positions in the `viewEvents` array.
   * If there are no empty positions in `viewEvents`, the function returns the original `viewEvents`
   * array.
   */
  insertEventsToEmptyPosition(viewEvents, events) {
    return viewEvents.map((item) => {
      if (events.length && !item) {
        const insertItem = events[0];
        events = events.slice(1);
        return insertItem;
      }
      else {
        return item;
      }
    });
  }
}
