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 { forceUpdate, h } from '@stencil/core';
import { MapToComponentField, MapToComponentMethod, VegaSlimmer } from 'vega-slimmer/core';
import { DomNodeSubjectObserverFactory } from '../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-observer-factory';
import { VegaInternalCalendarEventPreviewClear, VegaInternalCalendarEventPreviewHide, VegaInternalCalendarMonthEventsChange, } from '../../../../../helpers/event-manager/event-id/vega-internal-event-id';
import { createEnterKeyHandlerToTriggerClick } from '../../../../../utils/accessibility';
import { Observer } from '../../../../../helpers/change-manager/observer/observer';
import ChangeManager from '../../../../../helpers/change-manager/change-manager';
import { VegaPopoverHide } from '../../../../../helpers/event-manager/event-id/vega-event-id';
import DomNodeSubjectFactory from '../../../../../helpers/change-manager/subject/dom-node-subject/dom-node-subject-factory';
/** This code snippet defines a TypeScript class `VegaCalendarMonthEventRenderer` that extends `VegaSlimmer`. Here's a breakdown of what the class and its methods are doing: */
export class VegaCalendarMonthEventRenderer extends VegaSlimmer {
  constructor() {
    super(...arguments);
    this.maxMonthDisplayEventsCount = 2;
    this.popoverHideObserver = null;
  }
  /**
   * current row dates all events.
   *
   * @param {CalendarDate[]} rowDate the current view date object
   * @returns {Nullable<CalendarEvent>[][]} the current view events
   */
  getCurrentRowEvents(rowDate) {
    const result = [];
    rowDate.forEach((item) => {
      const currentDateEvents = this.calendarEventController.getCurrentDateEvents(item);
      result.push(currentDateEvents);
    });
    return this.fullDayEventLayoutRenderer.sortLongEvents(result);
  }
  /**
   * The function filterRowDisplayEvents processes a 2D array of CalendarEvent objects to limit the number of events displayed per row.
   *
   * @param {(CalendarEvent|null)[][]} rowEvents - `rowEvents` is an array of arrays of `CalendarEvent` objects. Each inner array represents events for a specific row in a calendar display.
   * @returns {Nullable<CalendarEvent>[][]} the current row should display events array
   */
  filterRowDisplayEvents(rowEvents) {
    const result = [];
    rowEvents.forEach((events) => {
      const displayEvents = events.length > this.maxMonthDisplayEventsCount
        ? events.slice(0, this.maxMonthDisplayEventsCount - 1)
        : events;
      result.push(displayEvents);
    });
    return this.hideTheCutOffEvents(rowEvents, result);
  }
  /**
   * Get the month event container element ref
   *
   * @returns {HTMLDivElement} the container element
   */
  getMonthEventContainerRef() {
    return this.eventContainerRef;
  }
  /* istanbul ignore next */
  /**
   * Get the more events popover box ref
   *
   * @returns {Nullable<HTMLVegaBoxElement>} the more events popover box element
   */
  getMoreEventsBoxRef() {
    return this.moreEventsBoxRef;
  }
  /**
   * render the current date events
   *
   * @param {CalendarDate} calendarDate current day
   * @param {Nullable<CalendarEvent>[]} allEvents current row events
   * @param {Nullable<CalendarEvent>[]} displayEvents current row should display events
   * @param {number} currentViewIndex current day index of week
   * @returns {HTMLDivElement} the events container
   */
  render(calendarDate, allEvents, displayEvents, currentViewIndex) {
    const hiddenEventsLength = allEvents
      .slice(displayEvents.length)
      .filter((item) => item).length;
    return (h("div", { class: "events-container", ref: (node) => (this.eventContainerRef = node) },
      h("div", { class: "event-list" }, this.fullDayEventLayoutRenderer.render(displayEvents, currentViewIndex, calendarDate)),
      this.renderMoreButton(allEvents, hiddenEventsLength, calendarDate)));
  }
  /**
   * Add a month event display count change observer, than update the component
   */
  addMaxDisplayCountChange() {
    DomNodeSubjectObserverFactory.addUniqueObserverToNode(this.host, VegaInternalCalendarMonthEventsChange, (payload) => {
      if (this.maxMonthDisplayEventsCount !== payload.detail) {
        this.maxMonthDisplayEventsCount = payload.detail;
        if (this.viewMode === 'month') {
          forceUpdate(this.host);
        }
      }
    });
  }
  /**
   * Render the event more button if there is no enough space to display all event
   *
   * @param {Nullable<CalendarEvent>[]} events all event list array
   * @param {number} moreItemsLength popover events length
   * @param {CalendarDate} calendarDate current date
   * @returns {Nullable<HTMLDivElement>} the more button or null
   */
  renderMoreButton(events, moreItemsLength, calendarDate) {
    if (moreItemsLength) {
      const backgroundColorEvents = events.filter((eventItem) => {
        return eventItem && (eventItem.isAllDayEvent || eventItem.isGroupEvent());
      });
      const otherEvents = events.filter((eventItem) => {
        return eventItem && !eventItem.isAllDayEvent && !eventItem.isGroupEvent();
      });
      return (h("div", { class: "month-event-more" },
        h("vega-popover", { trigger: "click", placement: "right", padding: '0', ref: (el) => {
            this.setPopoverHideObserver(el);
          }, isScreenPosition: true },
          h("div", { tabIndex: 0, slot: "popover-content", role: "button", class: "more-button", onKeyDown: createEnterKeyHandlerToTriggerClick() }, `${moreItemsLength} More`),
          h("vega-flex", { slot: "popover" },
            h("vega-box", { padding: 'size-12', width: 256 },
              h("vega-flex", { direction: "col", gap: "0", class: "group-events" },
                h("vega-font", { textAlign: "center", variant: "font-field-label", color: "text-primary", style: { padding: '4px 0', marginBottom: '8px' } }, `${calendarDate.date} ${calendarDate.getMonthName()} ${calendarDate.year}`),
                h("vega-box", { maxHeight: 'calc(60vh - 6px)', style: { overflowY: 'auto' }, padding: 'size-4', ref: (ref) => (this.moreEventsBoxRef = ref) },
                  h("vega-flex", { direction: "col", gap: "size-4", style: { paddingBottom: otherEvents.length ? '4px' : '0px' } }, backgroundColorEvents.map((item) => {
                    return this.eventItemRenderer.render(item, {
                      'month-event': true,
                      'calendar-event-large-size': true,
                      'calendar-event-in-popover': true,
                    }, calendarDate, true);
                  })),
                  otherEvents.map((item) => {
                    return this.eventItemRenderer.render(item, {
                      'month-event': true,
                      'calendar-event-large-size': true,
                      'calendar-event-in-popover': true,
                    }, calendarDate, true);
                  })))),
            h("div", { class: "preview-container", ref: (el) => {
                el
                  ? this.eventPreviewPopoverController.setEventPreviewContainerMap(events, calendarDate, el)
                  : this.eventPreviewPopoverController.deleteEventPreviewContainer(events, calendarDate);
              } })))));
    }
  }
  /*
   * The below method is e2e-test covered in
   * @see{module:vega-calendar-render-full-day-event-correct}
   */
  /* istanbul ignore next */
  /**
   * The `hideTheCutOffEvents` method in the `VegaCalendarMonthEventRenderer` class is responsible for removing any cut-off events from the displayed events in each row
   *
   * @param {Nullable<CalendarEvent>[][]} allEvents the all events
   * @param {Nullable<CalendarEvent>[][]} rowEvents the display events
   * @returns {Nullable<CalendarEvent>[][]} new event array
   */
  hideTheCutOffEvents(allEvents, rowEvents) {
    const result = [];
    const removeItems = [];
    const shouldCheckEvents = rowEvents
      .map((items) => items[items.length - 1])
      .filter((item) => item && item.isGroupEvent());
    if (shouldCheckEvents.length) {
      shouldCheckEvents.forEach((checkItem) => {
        if (allEvents.filter((items) => items.includes(checkItem)).length >
          rowEvents.filter((items) => items.includes(checkItem)).length) {
          removeItems.push(checkItem);
        }
      });
    }
    if (removeItems.length) {
      rowEvents.forEach((items) => {
        if (items.length &&
          items[items.length - 1] &&
          removeItems.includes(items[items.length - 1])) {
          result.push(items.slice(0, items.length - 1));
        }
        else {
          result.push(items);
        }
      });
      return result;
    }
    return rowEvents;
  }
  setPopoverHideObserver(popover) {
    if (popover) {
      this.popoverHideObserver = new Observer((_payload) => true, async () => await popover.hide());
      ChangeManager.register(DomNodeSubjectFactory.getSubject(this.host, VegaInternalCalendarEventPreviewHide), this.popoverHideObserver);
    }
    else if (this.popoverHideObserver) {
      ChangeManager.unregister(DomNodeSubjectFactory.getSubject(this.host, VegaInternalCalendarEventPreviewHide), this.popoverHideObserver);
    }
    // we should clear current event in vega-calendar-event-preview when popover hide
    popover &&
      DomNodeSubjectObserverFactory.addUniqueObserverToNode(popover, VegaPopoverHide, () => {
        ChangeManager.notify(DomNodeSubjectFactory.getSubject(this.renderer.getEventPreviewRef(), VegaInternalCalendarEventPreviewClear), {});
      });
  }
}
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "viewMode", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "host", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "calendarEventController", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "eventItemRenderer", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "fullDayEventLayoutRenderer", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "eventPreviewPopoverRenderer", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "renderer", void 0);
__decorate([
  MapToComponentField()
], VegaCalendarMonthEventRenderer.prototype, "eventPreviewPopoverController", void 0);
__decorate([
  MapToComponentMethod('componentWillLoad')
], VegaCalendarMonthEventRenderer.prototype, "addMaxDisplayCountChange", null);
