import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
import { k as differenceInMilliseconds, a as differenceInDays, g as getStartEndDateForInterval, c as differenceInMinutes, f as differenceInHours, l as getBeginningOfDay, i as differenceInMonths, j as daysInMonth } from './helpers.js';
import { r as requiredArgs } from './index4.js';

/**
 * @name differenceInSeconds
 * @category Second Helpers
 * @summary Get the number of seconds between the given dates.
 *
 * @description
 * Get the number of seconds between the given dates.
 *
 * ### v2.0.0 breaking changes:
 *
 * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
 *
 * @param {Date|Number} dateLeft - the later date
 * @param {Date|Number} dateRight - the earlier date
 * @returns {Number} the number of seconds
 * @throws {TypeError} 2 arguments required
 *
 * @example
 * // How many seconds are between
 * // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?
 * const result = differenceInSeconds(
 *   new Date(2014, 6, 2, 12, 30, 20, 0),
 *   new Date(2014, 6, 2, 12, 30, 7, 999)
 * )
 * //=> 12
 */

function differenceInSeconds(dirtyDateLeft, dirtyDateRight) {
  requiredArgs(2, arguments);
  var diff = differenceInMilliseconds(dirtyDateLeft, dirtyDateRight) / 1000;
  return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}

/**
 * @name differenceInWeeks
 * @category Week Helpers
 * @summary Get the number of full weeks between the given dates.
 *
 * @description
 * Get the number of full weeks between two dates. Fractional weeks are
 * truncated towards zero.
 *
 * One "full week" is the distance between a local time in one day to the same
 * local time 7 days earlier or later. A full week can sometimes be less than
 * or more than 7*24 hours if a daylight savings change happens between two dates.
 *
 * To ignore DST and only measure exact 7*24-hour periods, use this instead:
 * `Math.floor(differenceInHours(dateLeft, dateRight)/(7*24))|0`.
 *
 *
 * ### v2.0.0 breaking changes:
 *
 * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
 *
 * @param {Date|Number} dateLeft - the later date
 * @param {Date|Number} dateRight - the earlier date
 * @returns {Number} the number of full weeks
 * @throws {TypeError} 2 arguments required
 *
 * @example
 * // How many full weeks are between 5 July 2014 and 20 July 2014?
 * const result = differenceInWeeks(new Date(2014, 6, 20), new Date(2014, 6, 5))
 * //=> 2
 *
 * // How many full weeks are between
 * // 1 March 2020 0:00 and 6 June 2020 0:00 ?
 * // Note: because local time is used, the
 * // result will always be 8 weeks (54 days),
 * // even if DST starts and the period has
 * // only 54*24-1 hours.
 * const result = differenceInWeeks(
 *   new Date(2020, 5, 1),
 *   new Date(2020, 2, 6)
 * )
 * //=> 8
 */

function differenceInWeeks(dirtyDateLeft, dirtyDateRight) {
  requiredArgs(2, arguments);
  var diff = differenceInDays(dirtyDateLeft, dirtyDateRight) / 7;
  return diff > 0 ? Math.floor(diff) : Math.ceil(diff);
}

const ruxTrackCss = ":host{--grid-gap:100px}:host([slot=ruler]) .rux-timeline.rux-track{grid-template-rows:auto auto}.rux-track{background:var(--color-background-surface-default, #1b2d3e);width:fit-content;border-bottom:2px solid var(--color-background-base-default, #101923)}.rux-track__header{box-sizing:border-box;padding:11px 8px 13px 8px;background:var(--color-background-surface-default, #1b2d3e);border-right:2px solid var(--color-background-base-default, #101923);display:flex;align-items:center;font-family:var(--font-body-1-font-family, 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif);font-size:var(--font-body-1-font-size, 1rem);font-weight:var(--font-body-1-font-weight, 400);letter-spacing:var(--font-body-1-letter-spacing, 0.005em);position:sticky;left:0;min-width:184px;z-index:2}.rux-timeline{scrollbar-color:var(--color-border-interactive-muted, #2b659b);position:relative;display:grid;grid-template-rows:auto;background:var(--color-background-surface-default, #1b2d3e);background-image:repeating-linear-gradient(to left, var(--grid-line-color), var(--grid-line-color) 1px, transparent 1px, transparent var(--grid-gap))}.rux-track__played{grid-row-start:1;grid-column-start:2;grid-row-end:auto;background:var(--color-background-surface-selected, #1c3f5e)}.grid{background:repeating-linear-gradient(to left, var(--grid-line-color), var(--grid-line-color) 1px, transparent 1px, transparent var(--grid-gap));position:absolute;inset:0;pointer-events:none}.hidden{display:none}";

const RuxTrack = /*@__PURE__*/ proxyCustomElement(class RuxTrack extends HTMLElement {
  constructor() {
    super();
    this.__registerHost();
    this.__attachShadow();
    this.hasRuler = false;
    this.width = 0;
    this.columns = 0;
    this.interval = undefined;
    this.start = '';
    this.end = '';
    this.timezone = 'UTC';
    this.playhead = undefined;
  }
  handleUpdate(_newValue, old) {
    if (old) {
      this.initializeRows();
    }
  }
  handlePlayheadChange() {
    this.initializeRows();
  }
  handleTimezoneUpdate() {
    this.initializeRows();
  }
  handleTimeRegionChange(e) {
    this.initializeRows();
    e.stopPropagation();
  }
  connectedCallback() {
    this._handleSlotChange = this._handleSlotChange.bind(this);
  }
  /**
   * Tracks are displayed as a (CSS) grid of cells.
   * Each cell can represent a minute or hour depending on the interval.
   */
  _calculateGridColumnFromTime(time) {
    if (this.start) {
      let useStartEndDates = getStartEndDateForInterval(this.start, this.end, this.interval);
      if (this.interval === 'hour') {
        const difference = Math.abs(differenceInMinutes(useStartEndDates.timelineStart, new Date(time)));
        return difference + 2;
      }
      if (this.interval === 'minute') {
        const difference = Math.abs(differenceInSeconds(useStartEndDates.timelineStart, new Date(time)));
        return difference + 2;
      }
      if (this.interval === 'day') {
        return (Math.abs(differenceInHours(useStartEndDates.timelineStart, new Date(time))) + 2);
      }
      if (this.interval === 'week') {
        const timeAsDate = new Date(time);
        const numWeeks = Math.ceil(Math.abs(differenceInWeeks(useStartEndDates.timelineStart, getBeginningOfDay(timeAsDate, 0))));
        const weekStartsOnDay = useStartEndDates.timelineStart.getDay();
        let extraDays = timeAsDate.getDay();
        if (weekStartsOnDay > extraDays) {
          extraDays += 7;
        }
        return (Math.ceil((numWeeks + (extraDays - weekStartsOnDay) / 7) * 24) + 2);
      }
      if (this.interval === 'month') {
        // For a month, the timeline starts on the first of the month
        const timeAsDate = new Date(time);
        const numMonths = Math.abs(differenceInMonths(useStartEndDates.timelineStart, timeAsDate));
        const extraDays = timeAsDate.getDate() - 1;
        const daysInCurrentMonth = daysInMonth(timeAsDate);
        const extraHours = timeAsDate.getHours();
        return (Math.ceil((numMonths +
          (extraDays + extraHours / 24) /
            daysInCurrentMonth) *
          24) + 2);
      }
    }
    return 0;
  }
  _validateTimeRegion(start, end) {
    if (!start) {
      return {
        success: false,
        error: 'Time Region must have a start date provided',
      };
    }
    if (!end) {
      return {
        success: false,
        error: 'Time Region must have a end date provided',
      };
    }
    if (new Date(start) > new Date(end)) {
      return {
        success: false,
        error: `The Time Region start date must be before the end date: ${start} - ${end}`,
      };
    }
    if (new Date(start) > new Date(this.end)) {
      return {
        success: false,
        error: `The Time Region start date does not fall within the Timeline's range: ${start} - ${this.start}/${this.end}`,
      };
    }
    if (new Date(start) < new Date(this.start) &&
      new Date(end) < new Date(this.start)) {
      return {
        success: false,
        error: `The Time Region start and end dates do not fall within the Timeline's range: ${start} - ${end}`,
      };
    }
    return {
      success: true,
    };
  }
  /**
   * Time Regions are dumb and don't know anything about the grid.
   * The Track is responsible for lining up the Time Regions with the grid.
   */
  initializeRows() {
    if (this.playhead) {
      this.playedIndicator.style.gridColumnEnd = this._calculateGridColumnFromTime(this.playhead).toString();
    }
    const children = [...this.el.children].filter((el) => el.tagName.toLowerCase() === 'rux-time-region');
    let useStartEndDates = getStartEndDateForInterval(this.start, this.end, this.interval);
    children.forEach((el) => {
      const isHidden = el.style.visibility === 'hidden';
      const isValid = this._validateTimeRegion(el.start, el.end);
      /**
       * Store temp vars to use for calculating a Time Region's position in the grid
       * If a Time Region's range is outside the Timeline's range (a partial event),
       * visually it is treated as if its start/end dates = the timeline's.
       * */
      let start = el.start;
      let end = el.end;
      let startDate = new Date(el.start);
      let endDate = new Date(el.end);
      if (isValid.success) {
        if (startDate < useStartEndDates.timelineStart &&
          endDate > useStartEndDates.timelineEnd) {
          el.partial = 'ongoing';
          start = useStartEndDates.timelineStart.toISOString();
          end = useStartEndDates.timelineEnd.toISOString();
        }
        else if (startDate < useStartEndDates.timelineStart) {
          el.partial = 'start';
          start = this.start;
        }
        else if (endDate > useStartEndDates.timelineEnd) {
          el.partial = 'end';
          end = useStartEndDates.timelineEnd.toISOString();
        }
        else {
          el.partial = 'none';
        }
        el.timezone = this.timezone;
        el.style.gridRow = '1';
        el.style.display = 'block';
        const gridColumn = `${this._calculateGridColumnFromTime(start)} / ${this._calculateGridColumnFromTime(end)}`;
        el.style.gridColumn = gridColumn;
      }
      else {
        if (!isHidden) {
          el.style.display = 'none';
        }
      }
    });
  }
  _handleSlotChange() {
    this.initializeRows();
    const hasRuler = [...this.el.children].find((el) => el.tagName.toLowerCase() === 'rux-ruler');
    this.hasRuler = !!hasRuler;
  }
  renderCssGrid() {
    //we need the width of an hour so we need the interval * whatever the width of a grid col is
    const getCols = () => {
      if (['minute', 'hour'].includes(this.interval))
        return 60;
      if (['day', 'week', 'month'].includes(this.interval))
        return 24;
      return 60;
    };
    const span = getCols();
    const width = span * this.width;
    // we set this as --grid-gap and then use that variable
    // in rux-track.scss to set the gap between lines
    return `${width}px`;
  }
  render() {
    return (h(Host, null, h("div", { class: "rux-timeline rux-track", style: {
        gridTemplateColumns: `[header] 200px repeat(${this.columns}, ${this.width}px)`,
        '--grid-gap': this.renderCssGrid(),
      }, part: "container" }, h("div", { class: "rux-track__header", part: "track-header", style: {
        gridRow: '1 / -1',
      } }, h("slot", { name: "label" })), h("slot", { onSlotchange: this._handleSlotChange }), h("div", { class: {
        'rux-track__played': this.playhead,
        hidden: this.hasRuler,
      }, ref: (el) => (this.playedIndicator = el) }), h("div", { class: "grid" }))));
  }
  get el() { return this; }
  static get watchers() { return {
    "start": ["handleUpdate"],
    "end": ["handleUpdate"],
    "interval": ["handleUpdate"],
    "playhead": ["handlePlayheadChange"],
    "timezone": ["handleTimezoneUpdate"]
  }; }
  static get style() { return ruxTrackCss; }
}, [1, "rux-track", {
    "width": [514],
    "columns": [514],
    "interval": [520],
    "start": [513],
    "end": [513],
    "timezone": [513],
    "playhead": [520],
    "hasRuler": [32]
  }, [[0, "ruxtimeregionchange", "handleTimeRegionChange"]]]);
function defineCustomElement() {
  if (typeof customElements === "undefined") {
    return;
  }
  const components = ["rux-track"];
  components.forEach(tagName => { switch (tagName) {
    case "rux-track":
      if (!customElements.get(tagName)) {
        customElements.define(tagName, RuxTrack);
      }
      break;
  } });
}

export { RuxTrack as R, defineCustomElement as d };
