import { unsafeCSS, LitElement, html } from "lit";
import { property, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { styleMap } from "lit/directives/style-map.js";
import { customElement } from "../../decorator.js";
import componentStyle from "./sequence-loading-spinner.css.js";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result) __defProp(target, key, result);
  return result;
};
const DETERMINATE_MS_PER_PERCENT = 50;
const DETERMINATE_MIN_DURATION_MS = 1200;
const DETERMINATE_MAX_DURATION_MS = 9e3;
const DETERMINATE_START_DELAY_MS = 1e3;
var SequenceLoadingSpinnerType = /* @__PURE__ */ ((SequenceLoadingSpinnerType2) => {
  SequenceLoadingSpinnerType2["indicator"] = "indicator";
  SequenceLoadingSpinnerType2["indicatorPoint"] = "indicator-point";
  SequenceLoadingSpinnerType2["tag"] = "tag";
  SequenceLoadingSpinnerType2["tagPoint"] = "tag-point";
  SequenceLoadingSpinnerType2["button"] = "button";
  SequenceLoadingSpinnerType2["buttonPoint"] = "button-point";
  return SequenceLoadingSpinnerType2;
})(SequenceLoadingSpinnerType || {});
var SequenceLoadingSpinnerProgressionType = /* @__PURE__ */ ((SequenceLoadingSpinnerProgressionType2) => {
  SequenceLoadingSpinnerProgressionType2["determinate"] = "determinate";
  SequenceLoadingSpinnerProgressionType2["scanning"] = "scanning";
  return SequenceLoadingSpinnerProgressionType2;
})(SequenceLoadingSpinnerProgressionType || {});
let ObcSequenceLoadingSpinner = class extends LitElement {
  constructor() {
    super(...arguments);
    this.type = "indicator";
    this.progression = "determinate";
    this.rotationDurationMs = 1e3;
    this.progressPercent = 0;
    this.determinateDisplayPercent = 0;
    this.fillAnimGeneration = 0;
  }
  get isButtonType() {
    return this.type === "button" || this.type === "button-point";
  }
  get clampedRotationDurationMs() {
    const duration = Number.isFinite(this.rotationDurationMs) ? this.rotationDurationMs : 1e3;
    return Math.max(100, duration);
  }
  get clampedProgressPercent() {
    const percent = Number.isFinite(this.progressPercent) ? this.progressPercent : 0;
    return Math.min(100, Math.max(0, percent));
  }
  get determinateRenderPercent() {
    return this.hasUpdated ? this.determinateDisplayPercent : this.clampedProgressPercent;
  }
  get rootClasses() {
    const isDeterminate = this.progression === "determinate";
    const p = this.determinateRenderPercent;
    return {
      "sequence-loading-spinner": true,
      [`type-${this.type}`]: true,
      [`progression-${this.progression}`]: true,
      "progress-empty": isDeterminate && p <= 0,
      "progress-full": isDeterminate && p >= 100
    };
  }
  get spinnerStyle() {
    if (this.progression === "scanning") {
      return styleMap({
        "--spinner-rotation-duration": `${this.clampedRotationDurationMs}ms`
      });
    }
    const percent = this.determinateRenderPercent;
    return styleMap({
      "--spinner-progress-deg": `${percent * 3.6}deg`
    });
  }
  disconnectedCallback() {
    this.clearFillAnimation();
    super.disconnectedCallback();
  }
  connectedCallback() {
    super.connectedCallback();
    if (!this.hasUpdated) return;
    if (this.progression !== "determinate") {
      return;
    }
    if (this.clampedProgressPercent >= 100) {
      return;
    }
    this.startDeterminateFillAnimation();
  }
  updated(changed) {
    super.updated(changed);
    if (this.progression === "scanning") {
      this.clearFillAnimation();
      return;
    }
    if (this.progression !== "determinate") {
      return;
    }
    const rerun = ["progressPercent", "progression"].some(
      (k) => changed.has(k)
    );
    if (!rerun) {
      return;
    }
    this.startDeterminateFillAnimation();
  }
  clearFillAnimation() {
    if (this.determinateFillFrame !== void 0) {
      window.cancelAnimationFrame(this.determinateFillFrame);
    }
    this.determinateFillFrame = void 0;
    window.clearTimeout(this.determinateStartDelayTimeout);
    this.determinateStartDelayTimeout = void 0;
    this.fillAnimGeneration++;
  }
  startDeterminateFillAnimation() {
    this.clearFillAnimation();
    const generation = this.fillAnimGeneration;
    const start = this.clampedProgressPercent;
    const remaining = Math.max(0, 100 - start);
    const duration = Math.min(
      DETERMINATE_MAX_DURATION_MS,
      Math.max(
        DETERMINATE_MIN_DURATION_MS,
        remaining * DETERMINATE_MS_PER_PERCENT
      )
    );
    if (start >= 100) {
      this.determinateDisplayPercent = 100;
      return;
    }
    this.determinateDisplayPercent = start;
    let startTime = void 0;
    const tick = () => {
      if (generation !== this.fillAnimGeneration) return;
      const now = performance.now();
      if (startTime === void 0) {
        startTime = now;
      }
      const elapsed = now - startTime;
      const t = Math.min(1, elapsed / Math.max(duration, 1));
      this.determinateDisplayPercent = start + (100 - start) * t;
      if (t < 1) {
        this.determinateFillFrame = window.requestAnimationFrame(tick);
      } else {
        this.determinateFillFrame = void 0;
        this.determinateDisplayPercent = 100;
      }
    };
    this.determinateStartDelayTimeout = window.setTimeout(() => {
      if (generation !== this.fillAnimGeneration) return;
      this.determinateFillFrame = window.requestAnimationFrame(tick);
    }, DETERMINATE_START_DELAY_MS);
  }
  render() {
    const style = this.spinnerStyle;
    const content = html`
      <span class="spinner" part="spinner" aria-hidden="true" style=${style}>
        <span class="cap cap-start" aria-hidden="true"></span>
        <span class="cap cap-end" aria-hidden="true"></span>
      </span>
    `;
    return this.isButtonType ? html`
          <button
            type="button"
            class=${classMap(this.rootClasses)}
            part="wrapper"
            aria-label="Loading"
            disabled
          >
            ${content}
          </button>
        ` : html`
          <span class=${classMap(this.rootClasses)} part="wrapper">
            ${content}
          </span>
        `;
  }
};
ObcSequenceLoadingSpinner.styles = unsafeCSS(componentStyle);
__decorateClass([
  property({ type: String })
], ObcSequenceLoadingSpinner.prototype, "type", 2);
__decorateClass([
  property({ type: String })
], ObcSequenceLoadingSpinner.prototype, "progression", 2);
__decorateClass([
  property({ type: Number, attribute: "rotation-duration-ms" })
], ObcSequenceLoadingSpinner.prototype, "rotationDurationMs", 2);
__decorateClass([
  property({ type: Number, attribute: "progress-percent" })
], ObcSequenceLoadingSpinner.prototype, "progressPercent", 2);
__decorateClass([
  state()
], ObcSequenceLoadingSpinner.prototype, "determinateDisplayPercent", 2);
ObcSequenceLoadingSpinner = __decorateClass([
  customElement("obc-sequence-loading-spinner")
], ObcSequenceLoadingSpinner);
export {
  ObcSequenceLoadingSpinner,
  SequenceLoadingSpinnerProgressionType,
  SequenceLoadingSpinnerType
};
//# sourceMappingURL=sequence-loading-spinner.js.map
