import { unsafeCSS, LitElement, html } from "lit";
import { property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import componentStyle from "./slider.css.js";
import "../icon-button/icon-button.js";
import { classMap } from "lit/directives/class-map.js";
import { customElement } from "../../decorator.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;
};
var ObcSliderVariant = /* @__PURE__ */ ((ObcSliderVariant2) => {
  ObcSliderVariant2["Normal"] = "normal";
  ObcSliderVariant2["Enhanced"] = "enhanced";
  ObcSliderVariant2["NoInput"] = "no-input";
  return ObcSliderVariant2;
})(ObcSliderVariant || {});
let ObcSlider = class extends LitElement {
  constructor() {
    super(...arguments);
    this.value = 50;
    this.min = 0;
    this.max = 100;
    this.stepClick = 10;
    this.variant = "normal";
    this.hasLeftIcon = false;
    this.hasRightIcon = false;
    this.allowSeeking = false;
    this.seekingSpeed = 1 / 3;
    this.disabled = false;
    this.animationFrame = null;
    this.isMouseDown = false;
    this.isTouchActive = false;
    this.targetValue = 0;
    this.isDragging = false;
    this.animationStartTime = null;
    this.animationStartValue = 0;
    this.onWindowMouseMove = (e) => {
      this.onMouseMove(e);
    };
    this.onWindowMouseUp = () => {
      this.onMouseUp();
    };
    this.onWindowTouchMove = (e) => {
      this.onTouchMove(e);
    };
    this.onWindowTouchEnd = () => {
      this.onTouchEnd();
    };
  }
  /**
   * Handles input changes from the slider or buttons.
   * Fires the `value` event with the new value.
   *
   * @param value - The new value to set.
   * @fires value
   */
  onInput(value) {
    this.value = value;
    this.dispatchEvent(new CustomEvent("value", { detail: this.value }));
  }
  /**
   * Decrements the value by `stepClick` when the left icon button is clicked.
   */
  onReduceClick() {
    if (this.disabled) return;
    this.onInput(Math.max(this.value - this.stepClick, this.min));
  }
  /**
   * Increments the value by `stepClick` when the right icon button is clicked.
   */
  onIncreaseClick() {
    if (this.disabled) return;
    this.onInput(Math.min(this.value + this.stepClick, this.max));
  }
  get slider() {
    return this.renderRoot.querySelector('input[type="range"]');
  }
  isClickingThumb(e) {
    const rect = this.slider.getBoundingClientRect();
    const left = rect.left + 24;
    const width = rect.width - 48;
    const thumbWidth = 48;
    const ratioValue = parseFloat(this.slider.value) / (parseFloat(this.slider.max) - parseFloat(this.slider.min));
    const thumbCenter = left + width * ratioValue;
    let clientX;
    if (e instanceof TouchEvent) {
      clientX = e.touches[0].clientX;
    } else {
      clientX = e.clientX;
    }
    const isNearThumb = Math.abs(clientX - thumbCenter) <= thumbWidth / 2;
    return isNearThumb;
  }
  onMouseDown(e) {
    if (this.variant === "no-input" || this.disabled) return;
    if (this.isClickingThumb(e)) return;
    this.isMouseDown = true;
    this.updateTargetValue(e);
    e.preventDefault();
    window.addEventListener("mousemove", this.onWindowMouseMove);
    window.addEventListener("mouseup", this.onWindowMouseUp);
    this.startAnimation();
  }
  onTouchStart(e) {
    if (this.variant === "no-input" || this.disabled) return;
    if (this.isClickingThumb(e)) return;
    this.isTouchActive = true;
    this.updateTargetValue(e);
    e.preventDefault();
    window.addEventListener("touchmove", this.onWindowTouchMove, {
      passive: false
    });
    window.addEventListener("touchend", this.onWindowTouchEnd);
    this.startAnimation();
  }
  onMouseMove(e) {
    if (this.isMouseDown) {
      this.updateTargetValue(e);
    }
  }
  onTouchMove(e) {
    if (this.isTouchActive) {
      this.updateTargetValue(e);
    }
  }
  onMouseUp() {
    this.isMouseDown = false;
    window.removeEventListener("mousemove", this.onWindowMouseMove);
    window.removeEventListener("mouseup", this.onWindowMouseUp);
    this.stopAnimation();
  }
  onTouchEnd() {
    this.isTouchActive = false;
    window.removeEventListener("touchmove", this.onWindowTouchMove);
    window.removeEventListener("touchend", this.onWindowTouchEnd);
    this.stopAnimation();
  }
  updateTargetValue(e) {
    const rect = this.slider.getBoundingClientRect();
    const left = rect.left + 24;
    const width = rect.width - 48;
    const x = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
    const percent = (x - left) / width;
    const min = parseFloat(this.slider.min);
    const max = parseFloat(this.slider.max);
    const unroundedValue = min + (max - min) * percent;
    if (this.step) {
      this.targetValue = Math.round(unroundedValue / this.step) * this.step;
    } else {
      this.targetValue = unroundedValue;
    }
  }
  startAnimation() {
    this.isDragging = this.allowSeeking;
    this.animationStartTime = performance.now();
    this.animationStartValue = parseFloat(this.slider.value);
    const min = parseFloat(this.slider.min);
    const max = parseFloat(this.slider.max);
    const step = this.step;
    const duration = 1 / this.seekingSpeed * 1e3;
    const direction = this.targetValue > this.animationStartValue ? 1 : -1;
    const animate = () => {
      let nextValue = this.targetValue;
      if (!this.isDragging) {
        const now = performance.now();
        const elapsed = now - (this.animationStartTime ?? now);
        const range = Math.abs(max - min);
        const expectedProgress = Math.min(elapsed / duration, 1);
        const expectedValue = this.animationStartValue + direction * range * expectedProgress;
        if (direction > 0) {
          nextValue = step === void 0 ? expectedValue : Math.ceil((expectedValue - min) / step) * step + min;
          nextValue = Math.min(this.targetValue, nextValue);
        } else {
          nextValue = step === void 0 ? expectedValue : Math.floor((expectedValue - min) / step) * step + min;
          nextValue = Math.max(this.targetValue, nextValue);
        }
      }
      if (parseFloat(this.slider.value) !== nextValue) {
        this.slider.value = String(nextValue);
        this.slider.dispatchEvent(new Event("input"));
      }
      if (direction > 0 && nextValue < this.targetValue || direction < 0 && nextValue > this.targetValue) {
        this.animationFrame = requestAnimationFrame(animate);
      } else if (this.isMouseDown || this.isTouchActive) {
        this.animationStartTime = performance.now();
        this.animationStartValue = parseFloat(this.slider.value);
        this.animationFrame = requestAnimationFrame(animate);
        this.isDragging = true;
      }
    };
    this.animationFrame = requestAnimationFrame(animate);
  }
  stopAnimation() {
    if (this.animationFrame !== null) {
      cancelAnimationFrame(this.animationFrame);
      this.animationFrame = null;
    }
  }
  render() {
    return html`
      ${this.hasLeftIcon ? html` <obc-icon-button
            ?disabled=${this.disabled}
            @click=${this.onReduceClick}
            variant="normal"
          >
            <slot name="icon-left"></slot>
          </obc-icon-button>` : null}
      <div
        class=${classMap({
      wrapper: true,
      [this.variant]: true,
      disabled: this.disabled
    })}
      >
        <div class="track"></div>
        <input
          type="range"
          min=${this.min}
          max=${this.max}
          step=${ifDefined(this.step)}
          .value=${this.value.toString()}
          ?disabled=${this.variant === "no-input" || this.disabled}
          class="slider"
          @input=${(event) => {
      this.value = Number(event.target.value);
      this.dispatchEvent(new CustomEvent("value", { detail: this.value }));
    }}
          @mousedown=${this.onMouseDown}
          @touchstart=${this.onTouchStart}
          @mousemove=${this.onMouseMove}
          @touchmove=${this.onTouchMove}
          @mouseup=${this.onMouseUp}
          @touchend=${this.onTouchEnd}
        />
        <div
          class="interactive-track-hover"
          @mousedown=${this.onMouseDown}
          @touchstart=${this.onTouchStart}
          @mousemove=${this.onMouseMove}
          @touchmove=${this.onTouchMove}
          @mouseup=${this.onMouseUp}
          @touchend=${this.onTouchEnd}
        ></div>
        <div
          class="container-hover"
          @mousedown=${this.onMouseDown}
          @touchstart=${this.onTouchStart}
          @mousemove=${this.onMouseMove}
          @touchmove=${this.onTouchMove}
          @mouseup=${this.onMouseUp}
          @touchend=${this.onTouchEnd}
        ></div>
        <div class="interactive-track"></div>
        <div class="thumb"></div>
      </div>
      ${this.hasRightIcon ? html`<obc-icon-button
            ?disabled=${this.disabled}
            @click=${this.onIncreaseClick}
            variant="normal"
          >
            <slot name="icon-right"></slot>
          </obc-icon-button>` : null}
    `;
  }
};
ObcSlider.styles = unsafeCSS(componentStyle);
__decorateClass([
  property({ type: Number })
], ObcSlider.prototype, "value", 2);
__decorateClass([
  property({ type: Number })
], ObcSlider.prototype, "min", 2);
__decorateClass([
  property({ type: Number })
], ObcSlider.prototype, "max", 2);
__decorateClass([
  property({ type: Number })
], ObcSlider.prototype, "step", 2);
__decorateClass([
  property({ type: Number })
], ObcSlider.prototype, "stepClick", 2);
__decorateClass([
  property({ type: String })
], ObcSlider.prototype, "variant", 2);
__decorateClass([
  property({ type: Boolean })
], ObcSlider.prototype, "hasLeftIcon", 2);
__decorateClass([
  property({ type: Boolean })
], ObcSlider.prototype, "hasRightIcon", 2);
__decorateClass([
  property({ type: Boolean })
], ObcSlider.prototype, "allowSeeking", 2);
__decorateClass([
  property({ type: Number })
], ObcSlider.prototype, "seekingSpeed", 2);
__decorateClass([
  property({ type: Boolean })
], ObcSlider.prototype, "disabled", 2);
ObcSlider = __decorateClass([
  customElement("obc-slider")
], ObcSlider);
export {
  ObcSlider,
  ObcSliderVariant
};
//# sourceMappingURL=slider.js.map
