/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { css, isServer, html } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { d as dateFromISO, a as dateToISO, n as nextMonth, p as prevMonth, g as getDaysDiff, b as dateFromRange, s as sameDate, c as getFirstValidDateInMonth, i as inRange } from "../../chunks/date.js";
import { n as numberStringFormatter, g as getDateTimeFormat } from "../../chunks/locale.js";
import { u as useT9n } from "../../chunks/useT9n.js";
import { u as useSetFocus } from "../../chunks/useSetFocus.js";
import { g as getMinMaxSource, a as getValueAsDateRange, b as applyLocaleOverride, c as getLocaleData } from "../../chunks/utils3.js";
const HEADING_LEVEL = 2;
const DATE_PICKER_FORMAT_OPTIONS = { dateStyle: "full" };
const CSS = {
  container: "container"
};
const styles = css`:host{box-sizing:border-box;background-color:var(--calcite-color-foreground-1);color:var(--calcite-color-text-2);font-size:var(--calcite-font-size--1)}:host *{box-sizing:border-box}:host{display:inline-block;inline-size:100%;overflow:visible;border-width:1px;border-style:solid;vertical-align:top;border-color:var(--calcite-date-picker-border-color, var(--calcite-color-border-3));border-radius:var(--calcite-date-picker-corner-radius, 0)}:host([scale=s]){inline-size:236px;min-inline-size:216px;max-inline-size:380px}:host([scale=s][range][layout=horizontal][calendars="2"]){inline-size:480px;min-inline-size:432px;max-inline-size:772px}:host([scale=m]){inline-size:298px;min-inline-size:272px;max-inline-size:480px}:host([scale=m][layout=horizontal][range][calendars="2"]){inline-size:608px;min-inline-size:544px;max-inline-size:972px}:host([scale=l]){inline-size:334px;min-inline-size:320px;max-inline-size:600px}:host([scale=l][layout=horizontal][range][calendars="2"]){inline-size:684px;min-inline-size:640px;max-inline-size:1212px}.container{outline:2px solid transparent;outline-offset:2px}:host([hidden]){display:none}[hidden]{display:none}`;
class DatePicker extends LitElement {
  constructor() {
    super();
    this.rangeValueChangedByUser = false;
    this.messages = useT9n({ blocking: true });
    this.focusSetter = useSetFocus()(this);
    this.calendars = 2;
    this.layout = "horizontal";
    this.monthStyle = "wide";
    this.proximitySelectionDisabled = false;
    this.range = false;
    this.scale = "m";
    this.calciteDatePickerChange = createEvent({ cancelable: false });
    this.calciteDatePickerRangeChange = createEvent({ cancelable: false });
    this.listen("keydown", this.keyDownHandler);
  }
  static {
    this.properties = { activeEndDate: [16, {}, { state: true }], activeStartDate: [16, {}, { state: true }], dateTimeFormat: [16, {}, { state: true }], hoverRange: [16, {}, { state: true }], localeData: [16, {}, { state: true }], activeDate: [0, {}, { attribute: false }], activeRange: [3, {}, { reflect: true }], calendars: [11, {}, { type: Number, reflect: true }], headingLevel: [11, {}, { type: Number, reflect: true }], layout: [3, {}, { reflect: true }], max: [3, {}, { reflect: true }], maxAsDate: [0, {}, { attribute: false }], messageOverrides: [0, {}, { attribute: false }], min: [3, {}, { reflect: true }], minAsDate: [0, {}, { attribute: false }], monthStyle: 1, numberingSystem: [3, {}, { reflect: true }], proximitySelectionDisabled: [7, {}, { reflect: true, type: Boolean }], range: [7, {}, { reflect: true, type: Boolean }], scale: [3, {}, { reflect: true }], value: 1, valueAsDate: [0, {}, { attribute: false }] };
  }
  static {
    this.styles = styles;
  }
  async reset() {
    this.resetActiveDates();
    this.rangeValueChangedByUser = false;
  }
  async setFocus(options) {
    return this.focusSetter(() => this.el, options);
  }
  async load() {
    await this.loadLocaleData();
  }
  willUpdate(changes) {
    if (changes.has("value")) {
      this.valueHandler(this.value);
    }
    if (changes.has("valueAsDate")) {
      this.valueAsDateWatcher(this.valueAsDate);
    }
    const minSource = getMinMaxSource(changes, "min");
    const maxSource = getMinMaxSource(changes, "max");
    if (minSource === "min") {
      this.minAsDate = dateFromISO(this.min);
    } else if (minSource === "minAsDate") {
      this.minAsDate = dateFromISO(dateToISO(this.minAsDate));
    }
    if (maxSource === "max") {
      this.maxAsDate = dateFromISO(this.max);
    } else if (maxSource === "maxAsDate") {
      this.maxAsDate = dateFromISO(dateToISO(this.maxAsDate));
    }
    if (changes.has("range") && this.range || changes.has("maxAsDate") || changes.has("minAsDate")) {
      this.setActiveStartAndEndDates();
    }
    if (changes.has("activeDate") && this.hasUpdated) {
      this.activeDateWatcher(this.activeDate);
    }
    if (changes.has("messages") && this.hasUpdated) {
      this.loadLocaleData().catch(console.error);
    }
  }
  activeDateWatcher(newValue) {
    if (!this.range) {
      return;
    }
    if (newValue) {
      this.activeStartDate = newValue;
      this.activeEndDate = nextMonth(this.activeStartDate);
    } else {
      this.resetActiveDates();
    }
  }
  valueHandler(value) {
    if (Array.isArray(value)) {
      this.valueAsDate = getValueAsDateRange(value);
      if (!this.rangeValueChangedByUser) {
        this.resetActiveDates();
      }
    } else if (value) {
      this.valueAsDate = dateFromISO(value);
    }
  }
  valueAsDateWatcher(newValueAsDate) {
    if (this.range && Array.isArray(newValueAsDate) && !this.rangeValueChangedByUser) {
      this.setActiveStartAndEndDates();
    } else if (!this.range && newValueAsDate && newValueAsDate !== this.activeDate) {
      this.activeDate = newValueAsDate;
    }
  }
  keyDownHandler(event) {
    if (event.key === "Escape") {
      this.resetActiveDates();
    }
  }
  async loadLocaleData() {
    if (isServer) {
      return;
    }
    const locale = applyLocaleOverride(this.messages._lang);
    numberStringFormatter.numberFormatOptions = {
      numberingSystem: this.numberingSystem,
      locale,
      useGrouping: false
    };
    this.localeData = await getLocaleData(locale);
    this.dateTimeFormat = getDateTimeFormat(locale, DATE_PICKER_FORMAT_OPTIONS);
  }
  monthHeaderSelectChange(event) {
    const date = new Date(event.detail.date);
    const position = event.detail.position;
    if (!this.range) {
      this.activeDate = date;
    } else {
      if (position === "end") {
        this.activeEndDate = date;
        this.activeStartDate = prevMonth(date);
      } else {
        this.activeStartDate = date;
        this.activeEndDate = nextMonth(date);
      }
    }
    event.stopPropagation();
  }
  monthActiveDateChange(event) {
    const date = new Date(event.detail);
    if (!this.range) {
      this.activeDate = date;
    } else {
      const month = date.getMonth();
      const isDateOutOfCurrentRange = month !== this.activeStartDate.getMonth() && (this.calendars === 1 || month !== nextMonth(this.activeStartDate).getMonth());
      if (this.activeRange === "end") {
        if (!this.activeEndDate || this.activeStartDate && isDateOutOfCurrentRange) {
          this.activeEndDate = date;
          this.activeStartDate = prevMonth(date);
        }
      } else {
        if (this.activeStartDate && isDateOutOfCurrentRange || !this.activeStartDate) {
          this.activeStartDate = date;
          this.activeEndDate = nextMonth(date);
        }
      }
    }
    event.stopPropagation();
  }
  monthHoverChange(event) {
    if (!this.range) {
      this.hoverRange = void 0;
      return;
    }
    const { valueAsDate } = this;
    const start = Array.isArray(valueAsDate) && valueAsDate[0];
    const end = Array.isArray(valueAsDate) && valueAsDate[1];
    const date = new Date(event.detail);
    this.hoverRange = {
      focused: this.activeRange || "start",
      start,
      end
    };
    if (this.proximitySelectionDisabled) {
      if (end && start || !end && date >= start) {
        this.hoverRange.focused = "end";
        this.hoverRange.end = date;
      } else if (!end && date < start) {
        this.hoverRange = {
          focused: "start",
          start: date,
          end: start
        };
      } else {
        this.hoverRange = void 0;
      }
    } else {
      if (this.activeRange) {
        if (this.activeRange === "end") {
          this.hoverRange.end = date;
          this.hoverRange.focused = "end";
        } else {
          this.hoverRange.start = date;
          this.hoverRange.focused = "start";
        }
      } else if (start && end) {
        const startDiff = Math.abs(getDaysDiff(date, start));
        const endDiff = Math.abs(getDaysDiff(date, end));
        if (date > end) {
          this.hoverRange.end = date;
          this.hoverRange.focused = "end";
        } else if (date < start) {
          this.hoverRange.start = date;
          this.hoverRange.focused = "start";
        } else if (date > start && date < end) {
          if (startDiff < endDiff) {
            this.hoverRange.start = date;
            this.hoverRange.focused = "start";
          } else {
            this.hoverRange.end = date;
            this.hoverRange.focused = "end";
          }
        }
      } else {
        if (start) {
          if (date < start) {
            this.hoverRange = {
              focused: "start",
              start: date,
              end: start
            };
          } else {
            this.hoverRange.end = date;
            this.hoverRange.focused = "end";
          }
        }
      }
    }
    event.stopPropagation();
  }
  monthMouseOutChange(event) {
    if (this.hoverRange) {
      this.hoverRange = void 0;
    }
    event.stopPropagation();
  }
  resetActiveDates() {
    const { valueAsDate } = this;
    if (!Array.isArray(valueAsDate) && valueAsDate && valueAsDate !== this.activeDate) {
      this.activeDate = new Date(valueAsDate);
    }
    if (Array.isArray(valueAsDate)) {
      if (valueAsDate[0] && valueAsDate[0] !== this.activeStartDate) {
        this.activeStartDate = new Date(valueAsDate[0]);
      }
      if (valueAsDate[1] && valueAsDate[1] !== this.activeEndDate) {
        this.activeEndDate = new Date(valueAsDate[1]);
      }
    }
    this.hoverRange = void 0;
  }
  getEndDate() {
    return Array.isArray(this.valueAsDate) && this.valueAsDate[1] || void 0;
  }
  setEndDate(date, emit = true) {
    const startDate = this.getStartDate();
    this.rangeValueChangedByUser = true;
    this.value = [dateToISO(startDate), dateToISO(date)];
    this.valueAsDate = [startDate, date];
    if (emit) {
      this.calciteDatePickerRangeChange.emit();
    }
  }
  getStartDate() {
    return Array.isArray(this.valueAsDate) && this.valueAsDate[0];
  }
  setStartDate(date, emit = true) {
    const endDate = this.getEndDate();
    this.rangeValueChangedByUser = true;
    this.value = [dateToISO(date), dateToISO(endDate)];
    this.valueAsDate = [date, endDate];
    if (emit) {
      this.calciteDatePickerRangeChange.emit();
    }
  }
  monthDateChange(event) {
    const date = new Date(event.detail);
    const isoDate = dateToISO(date);
    if (!this.range && isoDate === dateToISO(this.valueAsDate)) {
      return;
    }
    if (!this.range) {
      this.value = isoDate || "";
      this.valueAsDate = date || null;
      this.activeDate = date || null;
      this.calciteDatePickerChange.emit();
      return;
    }
    const start = this.getStartDate();
    const end = this.getEndDate();
    if (!start || !end && date < start) {
      if (start) {
        this.setEndDate(new Date(start));
      }
      if (this.activeRange == "end") {
        this.setEndDate(date);
      } else {
        this.setStartDate(date);
      }
    } else if (!end) {
      this.setEndDate(date);
    } else {
      if (this.proximitySelectionDisabled) {
        this.setStartDate(date, false);
        this.setEndDate(null, false);
        this.calciteDatePickerRangeChange.emit();
      } else {
        if (this.activeRange) {
          if (this.activeRange == "end") {
            this.setEndDate(date);
          } else {
            if (date > end) {
              this.setEndDate(null, false);
              this.activeEndDate = null;
            }
            this.setStartDate(date);
          }
        } else {
          const startDiff = getDaysDiff(date, start);
          const endDiff = getDaysDiff(date, end);
          if (endDiff === 0 || startDiff < 0) {
            this.setStartDate(date);
          } else if (startDiff === 0 || endDiff < 0) {
            this.setEndDate(date);
          } else if (startDiff < endDiff) {
            this.setStartDate(date);
          } else {
            this.setEndDate(date);
          }
        }
      }
    }
    event.stopPropagation();
    this.calciteDatePickerChange.emit();
  }
  getActiveDate(value, min, max) {
    const activeDate = dateFromRange(/* @__PURE__ */ new Date(), min, max);
    return dateFromRange(this.activeDate, min, max) || value || (sameDate(max, activeDate) && !this.range ? getFirstValidDateInMonth(activeDate, min, max) : activeDate);
  }
  getActiveEndDate(value, min, max) {
    return dateFromRange(this.activeEndDate, min, max) || value || dateFromRange(nextMonth(/* @__PURE__ */ new Date()), min, max);
  }
  setActiveStartAndEndDates() {
    if (this.range) {
      const startDate = dateFromRange(Array.isArray(this.valueAsDate) ? this.valueAsDate[0] : this.valueAsDate, this.minAsDate, this.maxAsDate);
      const endDate = dateFromRange(Array.isArray(this.valueAsDate) ? this.valueAsDate[1] : null, this.minAsDate, this.maxAsDate);
      this.activeStartDate = this.getActiveDate(startDate, this.minAsDate, this.maxAsDate);
      this.activeEndDate = this.getActiveEndDate(endDate, this.minAsDate, this.maxAsDate);
      if (sameDate(this.activeStartDate, this.activeEndDate)) {
        const previousMonthActiveDate = getFirstValidDateInMonth(prevMonth(this.activeEndDate), this.minAsDate, this.maxAsDate);
        const nextMonthActiveDate = nextMonth(this.activeEndDate);
        if (inRange(previousMonthActiveDate, this.minAsDate, this.maxAsDate)) {
          this.activeStartDate = previousMonthActiveDate;
        } else if (inRange(nextMonthActiveDate, this.minAsDate, this.maxAsDate)) {
          this.activeEndDate = nextMonthActiveDate;
        }
      }
    }
  }
  render() {
    const date = dateFromRange(this.range && Array.isArray(this.valueAsDate) ? this.valueAsDate[0] : this.valueAsDate, this.minAsDate, this.maxAsDate);
    const activeDate = this.getActiveDate(date, this.minAsDate, this.maxAsDate);
    const endDate = this.range && Array.isArray(this.valueAsDate) ? dateFromRange(this.valueAsDate[1], this.minAsDate, this.maxAsDate) : null;
    const minDate = this.range && this.activeRange ? this.activeRange === "start" ? this.minAsDate : date : this.minAsDate;
    const startCalendarActiveDate = this.range ? this.activeStartDate : activeDate;
    return html`<div aria-hidden class=${safeClassMap(CSS.container)} tabindex=-1>${this.renderMonth(startCalendarActiveDate, this.maxAsDate, minDate, date, endDate)}</div>`;
  }
  renderMonth(activeDate, maxDate, minDate, date, endDate) {
    return html`<calcite-date-picker-month .activeDate=${activeDate} .calendars=${this.calendars} .dateTimeFormat=${this.dateTimeFormat} .endDate=${this.range ? endDate : void 0} .headingLevel=${this.headingLevel || HEADING_LEVEL} .hoverRange=${this.hoverRange} .layout=${this.layout} .localeData=${this.localeData} .max=${maxDate} .messages=${this.messages} .min=${minDate} .monthStyle=${this.monthStyle} @calciteInternalDatePickerDayHover=${this.monthHoverChange} @calciteInternalDatePickerDaySelect=${this.monthDateChange} @calciteInternalDatePickerMonthActiveDateChange=${this.monthActiveDateChange} @calciteInternalDatePickerMonthChange=${this.monthHeaderSelectChange} @calciteInternalDatePickerMonthMouseOut=${this.monthMouseOutChange} .range=${this.range} .scale=${this.scale} .selectedDate=${this.activeRange === "end" ? endDate : date} .startDate=${this.range ? date : void 0}></calcite-date-picker-month>`;
  }
}
customElement("calcite-date-picker", DatePicker);
export {
  DatePicker
};
