var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { VegaSlimmer, MapToComponentField, MapToComponentMethod } from 'vega-slimmer/core';
import { CalendarEvent } from '../../../../../helpers/calendar/calendar-event';
import { LogUtility } from '../../../../../utils/log';
import ChangeManager from '../../../../../helpers/change-manager/change-manager';
import { VegaInternalCalendarEventPreviewHide } from '../../../../../helpers/event-manager/event-id/vega-internal-event-id';
import DomNodeSubjectFactory from '../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-factory';
/** The `VegaCalendarEventController` class in TypeScript manages calendar events, initializes event layouts, retrieves events for the current date, and checks if a date falls within the range of a calendar event. */
export class VegaCalendarEventController extends VegaSlimmer {
  constructor() {
    super(...arguments);
    // This map is cache for newly generated calendar events
    this.repeatEventMap = new Map();
  }
  /**
   * The function `getCurrentDateEvent` returns an array of calendar events for the current date, including both normal events and group events.
   *
   * @param {CalendarDate} date - The `date` parameter in the `getCurrentDateEvent` function is of type `CalendarDate`, which is used to represent a specific date with properties for year, month, and date.
   * @returns {CalendarEvent[]} The `getCurrentDateEvent` function returns an array of `CalendarEvent` objects. It
   * first retrieves all group events and normal events for the specified date, then filters out the
   * events that are specific to the current day. Finally, it concatenates the current day events with
   * the group events and returns the combined array.
   */
  getCurrentDateEvents(date) {
    const allEvents = this.createRepeatEvents();
    return allEvents.filter((item) => item.isCurrentDayEvent(date));
  }
  /**
   * initial calendar events when component props events change
   *
   * @param {VegaCalendarRawEvent[]} newEvents new event options array
   */
  updateAfterEventChange(newEvents) {
    this.initCalendarEvents(newEvents);
    this.repeatEventMap.clear();
  }
  /**
   * initial calendar events in first time
   */
  updateWhenComponentWillLoad() {
    this.initCalendarEvents(this.events);
  }
  /**
   * Handle timezone changes by updating all calendar events
   *
   */
  updateAfterTimezoneChange() {
    if (this.calendarEvents.length > 0) {
      this.calendarEvents.forEach((event) => event.updateTimezone(this.timezone));
    }
    ChangeManager.notify(DomNodeSubjectFactory.getSubject(this.host, VegaInternalCalendarEventPreviewHide), {});
    this.repeatEventMap.clear();
  }
  /**
   * initial calendar events
   *
   * @param {VegaCalendarRawEvent[]} newEvents new event options array
   */
  initCalendarEvents(newEvents) {
    const result = [];
    if (newEvents) {
      newEvents.forEach((item) => {
        try {
          const calendarEvent = new CalendarEvent(item, undefined, this.timezone);
          result.push(calendarEvent);
        }
        catch (_a) {
          LogUtility.warn('Invalid calendar event item:', item);
        }
      });
    }
    this.calendarEvents = result;
  }
  /**
   * We need generate new calendar event from the full-day repeat calendar event, so we can render those event as normal full-day event
   *
   * @returns {CalendarEvent[]} The `handleRepeatEvents` method returns an array of `CalendarEvent` objects.
   */
  createRepeatEvents() {
    const allEvents = this.calendarEvents;
    const otherEvents = [];
    const newRepeatEvents = [];
    allEvents.forEach((item) => {
      if (item.isRepeatEvent) {
        const repeatSeries = item.getRepeatSeries(this.currentPeriod);
        repeatSeries.forEach((series) => {
          newRepeatEvents.push(this.generateCalendarEventByRepeatSeries(item, series));
        });
      }
      else {
        otherEvents.push(item);
      }
    });
    return newRepeatEvents.concat(otherEvents);
  }
  /**
   * This function generates a calendar event based on a repeat series and stores it in a map to avoid duplicate creation.
   *
   * @param {CalendarEvent} calendarEvent - The `calendarEvent` parameter represents a single event on
   * a calendar. It contains information such as the event's start date, end date, and other details.
   * @param {CalendarDate} series - The repeat start date
   * @returns {CalendarEvent} The function `generateCalendarEventByRepeatSeries` returns a `CalendarEvent` object. If
   * the event key already exists in the `repeatEventMap`, it returns the corresponding `CalendarEvent`
   * object from the map. Otherwise, it creates a new `CalendarEvent` object based on the input
   * `calendarEvent` and `series` parameters, adds it to the `repeatEventMap`, and then
   */
  generateCalendarEventByRepeatSeries(calendarEvent, series) {
    const eventKey = `${calendarEvent.eventKey}-${series.year}${series.month}${series.date}`;
    if (this.repeatEventMap.has(eventKey)) {
      return this.repeatEventMap.get(eventKey);
    }
    else {
      const result = calendarEvent.copyTo(eventKey, series);
      this.repeatEventMap.set(eventKey, result);
      return result;
    }
  }
}
__decorate([
  MapToComponentField()
], VegaCalendarEventController.prototype, "host", void 0);
__decorate([
  MapToComponentField({ writable: true })
], VegaCalendarEventController.prototype, "calendarEvents", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarEventController.prototype, "currentPeriod", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarEventController.prototype, "events", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarEventController.prototype, "timezone", void 0);
__decorate([
  MapToComponentMethod('watchEventsChange')
], VegaCalendarEventController.prototype, "updateAfterEventChange", null);
__decorate([
  MapToComponentMethod('componentWillLoad')
], VegaCalendarEventController.prototype, "updateWhenComponentWillLoad", null);
__decorate([
  MapToComponentMethod('watchTimezoneChange')
], VegaCalendarEventController.prototype, "updateAfterTimezoneChange", null);
