import {
  __decorateClass,
  __privateAdd,
  __privateMethod
} from "../../chunks/chunk.QU3DSPNU.js";
var _GdsCalendar_instances, setSelectedDate_fn, handleKeyDown_fn;
import { localized, msg } from "@lit/localize";
import { html } from "lit";
import { property, query, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { when } from "lit/directives/when.js";
import {
  addDays,
  addMonths,
  getWeek,
  isSameDay,
  isSameMonth,
  lastDayOfMonth,
  setHours,
  subMonths
} from "date-fns";
import { GdsElement } from "../../gds-element.js";
import { gdsCustomElement } from "../../scoping.js";
import { tokens } from "../../tokens.style.js";
import { TransitionalStyles } from "../../transitional-styles.js";
import { watch } from "../../utils/decorators/watch.js";
import CalendarStyles from "./calendar.styles.js";
import { renderMonthGridView } from "./functions.js";
let GdsCalendar = class extends GdsElement {
  constructor() {
    super(...arguments);
    __privateAdd(this, _GdsCalendar_instances);
    this.min = new Date((/* @__PURE__ */ new Date()).getFullYear() - 10, 0, 1);
    this.max = new Date((/* @__PURE__ */ new Date()).getFullYear() + 10, 0, 1);
    this.focusedDate = /* @__PURE__ */ new Date();
    this.disabledWeekends = false;
    this.size = "large";
    this.showWeekNumbers = false;
    this.hideExtraneousDays = false;
    this.hideDayNames = false;
    this.dateLabelTemplate = (date) => date.toLocaleDateString(this._currentLocale, {
      weekday: "long",
      year: "numeric",
      month: "long",
      day: "numeric"
    });
    this._currentLocale = navigator.language;
  }
  get focusedMonth() {
    return this.focusedDate.getMonth();
  }
  set focusedMonth(month) {
    const lastOfSelectedMonth = lastDayOfMonth(
      new Date(this.focusedYear, month, 1)
    );
    const newFocusedDate = new Date(this.focusedDate);
    newFocusedDate.setDate(
      Math.min(this.focusedDate.getDate(), lastOfSelectedMonth.getDate())
    );
    newFocusedDate.setMonth(month);
    newFocusedDate.setHours(12, 0, 0, 0);
    this.focusedDate = newFocusedDate;
  }
  get focusedYear() {
    return this.focusedDate.getFullYear();
  }
  set focusedYear(year) {
    this.focusedDate = new Date(this.focusedDate.setFullYear(year));
  }
  /**
   * Returns the date cell element for the given day number.
   */
  getDateCell(dayNumber) {
    return this.shadowRoot?.querySelector(`#dateCell-${dayNumber}`);
  }
  connectedCallback() {
    super.connectedCallback();
    TransitionalStyles.instance.apply(this, "gds-calendar");
    this.addEventListener("keydown", __privateMethod(this, _GdsCalendar_instances, handleKeyDown_fn));
    window.addEventListener("lit-localize-status", (e) => {
      if (e.detail.status === "ready")
        this._currentLocale = e.detail.readyLocale;
    });
  }
  focus() {
    super.focus();
    this._elFocusedCell?.focus();
  }
  render() {
    const currentDate = /* @__PURE__ */ new Date();
    return html`<table
      role="grid"
      aria-label="${ifDefined(this.label)}"
      class="${classMap({
      small: Boolean(this.size === "small"),
      indicators: Boolean(this.customizedDates),
      "show-week-numbers": Boolean(this.showWeekNumbers)
    })}"
    >
      ${when(
      !this.hideDayNames,
      () => html`<thead role="rowgroup">
            <tr role="row">
              ${when(this.showWeekNumbers, () => html`<th></th>`)}
              <th>${msg("Mon").substring(0, 1)}</th>
              <th>${msg("Tue").substring(0, 1)}</th>
              <th>${msg("Wed").substring(0, 1)}</th>
              <th>${msg("Thu").substring(0, 1)}</th>
              <th>${msg("Fri").substring(0, 1)}</th>
              <th>${msg("Sat").substring(0, 1)}</th>
              <th>${msg("Sun").substring(0, 1)}</th>
            </tr>
          </thead>`
    )}
      <tbody role="rowgroup">
        ${renderMonthGridView(
      this.focusedDate,
      (weeks) => html`
            ${weeks.map(
        (week) => html`
                <tr role="row">
                  ${when(
          this.showWeekNumbers,
          () => html`<td
                        class="week-number disabled"
                        disabled
                        scope="row"
                      >
                        ${getWeek(week.days[0])}
                      </td>`
        )}
                  ${week.days.map((day) => {
          const customization = this.customizedDates && this.customizedDates.find((d) => isSameDay(d.date, day));
          const displayOptions = {
            // Defaults
            color: "currentColor",
            // Get baseline disabled state from the disabledDates prop (or false if unset)
            disabled: Boolean(
              this.disabledDates && this.disabledDates.some((d) => isSameDay(d, day))
            ),
            // Override with any customizations
            ...customization
          };
          const isOutsideCurrentMonth = !isSameMonth(
            this.focusedDate,
            day
          );
          const isOutsideMinMax = (day < this.min || day > this.max) && !isSameDay(day, this.min) && !isSameDay(day, this.max);
          const isWeekend = day.getDay() === 0 || day.getDay() === 6;
          const isDisabled = displayOptions.disabled || isOutsideMinMax || this.disabledWeekends && isWeekend;
          const shouldRenderBlank = this.hideExtraneousDays && isOutsideCurrentMonth;
          return shouldRenderBlank ? html`<td inert></td>` : html`
                          <td
                            role="${ifDefined(
            isDisabled ? void 0 : "gridcell"
          )}"
                            class="${classMap({
            small: Boolean(this.size === "small"),
            "custom-date": Boolean(customization),
            disabled: Boolean(isDisabled),
            today: isSameDay(currentDate, day),
            "outside-month": isOutsideCurrentMonth
          })}"
                            ?disabled=${isDisabled}
                            tabindex="${isSameDay(this.focusedDate, day) ? 0 : -1}"
                            aria-selected="${this.value && isSameDay(this.value, day) ? "true" : "false"}"
                            aria-label="${this.dateLabelTemplate(day)}"
                            @click=${() => isDisabled ? null : __privateMethod(this, _GdsCalendar_instances, setSelectedDate_fn).call(this, day)}
                            id="dateCell-${day.getDate()}"
                          >
                            <span
                              class="number"
                              style="--_color: ${displayOptions ? displayOptions?.color : ""}"
                              >${day.getDate()}</span
                            >

                            ${when(
            displayOptions.indicator,
            () => html`<span
                                  class="indicator-${displayOptions?.indicator}"
                                  style="--_color: ${displayOptions?.color}"
                                ></span>`
          )}
                          </td>
                        `;
        })}
                </tr>
              `
      )}
          `
    )}
      </tbody>
    </table>`;
  }
  _valueChanged() {
    if (!this.value) return;
    this.focusedDate = new Date(this.value);
  }
};
_GdsCalendar_instances = new WeakSet();
setSelectedDate_fn = function(date) {
  const dateOnMidDay = setHours(date, 12);
  this.value = dateOnMidDay;
  this.dispatchCustomEvent("change", {
    detail: dateOnMidDay,
    bubbles: false,
    composed: false
  });
};
handleKeyDown_fn = function(e) {
  let handled = false;
  let newFocusedDate = new Date(this.focusedDate);
  if (e.key === "ArrowLeft") {
    newFocusedDate = addDays(this.focusedDate, -1);
    handled = true;
  } else if (e.key === "ArrowRight") {
    newFocusedDate = addDays(this.focusedDate, 1);
    handled = true;
  } else if (e.key === "ArrowUp") {
    newFocusedDate = addDays(this.focusedDate, -7);
    handled = true;
  } else if (e.key === "ArrowDown") {
    newFocusedDate = addDays(this.focusedDate, 7);
    handled = true;
  } else if (e.key === "Enter" || e.key === " ") {
    if (!this._elFocusedCell?.hasAttribute("disabled")) {
      __privateMethod(this, _GdsCalendar_instances, setSelectedDate_fn).call(this, this.focusedDate);
    }
    handled = true;
  } else if (e.key === "Home") {
    newFocusedDate = new Date(this.focusedYear, this.focusedMonth, 1);
    handled = true;
  } else if (e.key === "End") {
    newFocusedDate = new Date(this.focusedYear, this.focusedMonth + 1, 0);
    handled = true;
  } else if (e.key === "PageUp") {
    newFocusedDate = subMonths(this.focusedDate, 1);
    handled = true;
  } else if (e.key === "PageDown") {
    newFocusedDate = addMonths(this.focusedDate, 1);
    handled = true;
  }
  if (newFocusedDate.getFullYear() >= this.min.getFullYear() && newFocusedDate.getFullYear() <= this.max.getFullYear()) {
    const proceed = this.dispatchCustomEvent("gds-date-focused", {
      detail: newFocusedDate,
      bubbles: false,
      composed: false
    });
    if (proceed) {
      this.focusedDate = newFocusedDate;
    }
  }
  if (handled) {
    e.preventDefault();
    e.stopPropagation();
    this.updateComplete.then(() => {
      this._elFocusedCell?.focus();
    });
  }
};
GdsCalendar.styles = [tokens, CalendarStyles];
GdsCalendar.shadowRootOptions = {
  mode: "open",
  delegatesFocus: true
};
__decorateClass([
  property()
], GdsCalendar.prototype, "value", 2);
__decorateClass([
  property({ type: Date })
], GdsCalendar.prototype, "min", 2);
__decorateClass([
  property({ type: Date })
], GdsCalendar.prototype, "max", 2);
__decorateClass([
  property()
], GdsCalendar.prototype, "focusedDate", 2);
__decorateClass([
  property({ type: Boolean, attribute: "disabled-weekends" })
], GdsCalendar.prototype, "disabledWeekends", 2);
__decorateClass([
  property({ type: Array, attribute: "disabled-dates" })
], GdsCalendar.prototype, "disabledDates", 2);
__decorateClass([
  property({ type: Number })
], GdsCalendar.prototype, "focusedMonth", 1);
__decorateClass([
  property({ type: Number })
], GdsCalendar.prototype, "focusedYear", 1);
__decorateClass([
  property({ reflect: true })
], GdsCalendar.prototype, "size", 2);
__decorateClass([
  property({ type: Boolean })
], GdsCalendar.prototype, "showWeekNumbers", 2);
__decorateClass([
  property({ type: Boolean })
], GdsCalendar.prototype, "hideExtraneousDays", 2);
__decorateClass([
  property({ type: Boolean })
], GdsCalendar.prototype, "hideDayNames", 2);
__decorateClass([
  property({ attribute: false })
], GdsCalendar.prototype, "customizedDates", 2);
__decorateClass([
  property()
], GdsCalendar.prototype, "label", 2);
__decorateClass([
  property({ attribute: false })
], GdsCalendar.prototype, "dateLabelTemplate", 2);
__decorateClass([
  state()
], GdsCalendar.prototype, "_currentLocale", 2);
__decorateClass([
  query('td[tabindex="0"]')
], GdsCalendar.prototype, "_elFocusedCell", 2);
__decorateClass([
  watch("value")
], GdsCalendar.prototype, "_valueChanged", 1);
GdsCalendar = __decorateClass([
  gdsCustomElement("gds-calendar"),
  localized()
], GdsCalendar);
export {
  GdsCalendar
};
