import { __decorate } from '../node_modules/.pnpm/@rollup_plugin-typescript@12.3.0_rollup@4.60.1_tslib@2.8.1_typescript@6.0.2/node_modules/tslib/tslib.es6.js';
import { css, LitElement, html } from 'lit';
import { property, state, customElement } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { styleMap } from 'lit/directives/style-map.js';
import { sharedStyles } from '../styles/shared-styles.js';
import { volumeOffIcon, volumeUpIcon } from '../icons/index.js';

let FwVolumeControl = class FwVolumeControl extends LitElement {
    constructor() {
        super(...arguments);
        this._hovered = false;
        this._focused = false;
        this._dragging = false;
        this._hasAudio = true;
        this._activePointerId = null;
        this._activeSliderTarget = null;
        this._boundStream = null;
        this._onStreamTrackChange = null;
        this._onGlobalPointerMove = (event) => {
            if (!this._dragging || this._activePointerId !== event.pointerId) {
                return;
            }
            const target = this._activeSliderTarget;
            if (!target) {
                return;
            }
            this._setVolumeFromClientX(event.clientX, target);
        };
        this._onGlobalPointerUp = (event) => {
            if (!this._dragging || this._activePointerId !== event.pointerId) {
                return;
            }
            this._endDragInteraction();
        };
        this._handleMouseEnter = () => {
            this._hovered = true;
        };
        this._handleMouseLeave = () => {
            if (this._dragging) {
                return;
            }
            this._hovered = false;
            this._focused = false;
        };
        this._handleFocusIn = () => {
            this._focused = true;
        };
        this._handleFocusOut = (event) => {
            if (this._dragging) {
                return;
            }
            const related = event.relatedTarget;
            if (!related || !this.renderRoot.contains(related)) {
                this._focused = false;
            }
        };
        this._onSliderPointerDown = (event) => {
            if (!this._hasAudio) {
                return;
            }
            event.preventDefault();
            const target = event.currentTarget;
            this._beginDragInteraction(target, event.pointerId);
            this._setVolumeFromClientX(event.clientX, target);
        };
        this._onWheel = (event) => {
            if (!this._hasAudio) {
                return;
            }
            event.preventDefault();
            const current = this.pc.s.isMuted ? 0 : Math.round(this.pc.s.volume * 100);
            const delta = event.deltaY < 0 ? 5 : -5;
            const next = Math.max(0, Math.min(100, current + delta));
            this.pc.setVolume(next / 100);
            if (this.pc.s.isMuted && next > 0) {
                this.pc.toggleMute();
            }
        };
    }
    get _expanded() {
        return this._hovered || this._focused || this._dragging;
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        this._endDragInteraction();
        this._unbindStreamListeners();
    }
    updated() {
        this._updateHasAudio();
    }
    _unbindStreamListeners() {
        if (this._boundStream && this._onStreamTrackChange) {
            this._boundStream.removeEventListener("addtrack", this._onStreamTrackChange);
            this._boundStream.removeEventListener("removetrack", this._onStreamTrackChange);
        }
        this._boundStream = null;
        this._onStreamTrackChange = null;
    }
    _updateHasAudio() {
        const video = this.pc?.s.videoElement;
        if (!video) {
            this._unbindStreamListeners();
            this._hasAudio = true;
            return;
        }
        // MediaStream: bind track change listeners (WebRTC tracks arrive async)
        if (video.srcObject instanceof MediaStream) {
            const stream = video.srcObject;
            if (stream !== this._boundStream) {
                this._unbindStreamListeners();
                this._boundStream = stream;
                this._onStreamTrackChange = () => {
                    this._hasAudio = stream.getAudioTracks().length > 0;
                };
                stream.addEventListener("addtrack", this._onStreamTrackChange);
                stream.addEventListener("removetrack", this._onStreamTrackChange);
            }
            this._hasAudio = stream.getAudioTracks().length > 0;
            return;
        }
        this._unbindStreamListeners();
        // Fallback: metadata for non-MediaStream sources.
        const mistHasAudio = this.pc?.s.streamState?.streamInfo?.hasAudio;
        if (mistHasAudio !== undefined) {
            this._hasAudio = mistHasAudio;
            return;
        }
        const maybeWithTracks = video;
        if (maybeWithTracks.audioTracks && typeof maybeWithTracks.audioTracks.length === "number") {
            this._hasAudio = maybeWithTracks.audioTracks.length > 0;
            return;
        }
        this._hasAudio = true;
    }
    _setVolumeFromClientX(clientX, target) {
        const rect = target.getBoundingClientRect();
        if (rect.width <= 0) {
            return;
        }
        const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
        this.pc.setVolume(pct);
        if (this.pc.s.isMuted && pct > 0) {
            this.pc.toggleMute();
        }
    }
    _beginDragInteraction(target, pointerId) {
        this._activePointerId = pointerId;
        this._activeSliderTarget = target;
        this._dragging = true;
        this._hovered = true;
        this._focused = true;
        try {
            target.setPointerCapture(pointerId);
        }
        catch {
            // Non-fatal: we still listen on window as a fallback.
        }
        window.addEventListener("pointermove", this._onGlobalPointerMove);
        window.addEventListener("pointerup", this._onGlobalPointerUp);
        window.addEventListener("pointercancel", this._onGlobalPointerUp);
    }
    _endDragInteraction() {
        const pointerId = this._activePointerId;
        const target = this._activeSliderTarget;
        if (pointerId != null && target) {
            try {
                if (target.hasPointerCapture(pointerId)) {
                    target.releasePointerCapture(pointerId);
                }
            }
            catch {
                // Ignore pointer-capture release errors.
            }
        }
        this._activePointerId = null;
        this._activeSliderTarget = null;
        this._dragging = false;
        window.removeEventListener("pointermove", this._onGlobalPointerMove);
        window.removeEventListener("pointerup", this._onGlobalPointerUp);
        window.removeEventListener("pointercancel", this._onGlobalPointerUp);
    }
    render() {
        const isMuted = this.pc.s.isMuted;
        const volume = this.pc.s.volume;
        const displayVolume = isMuted ? 0 : Math.max(0, Math.min(1, volume));
        return html `
      <div
        class=${classMap({
            "fw-volume-group": true,
            "fw-volume-group--expanded": this._expanded,
            "fw-volume-group--disabled": !this._hasAudio,
        })}
        role="group"
        aria-label="Volume controls"
        @mouseenter=${this._handleMouseEnter}
        @mouseleave=${this._handleMouseLeave}
        @focusin=${this._handleFocusIn}
        @focusout=${this._handleFocusOut}
        @click=${(event) => {
            if (this._hasAudio && event.target === event.currentTarget) {
                this.pc.toggleMute();
            }
        }}
        @wheel=${this._onWheel}
      >
        <button
          class="fw-volume-btn"
          type="button"
          @click=${() => {
            if (this._hasAudio) {
                this.pc.toggleMute();
            }
        }}
          ?disabled=${!this._hasAudio}
          aria-label=${!this._hasAudio
            ? "No audio"
            : isMuted
                ? this.pc.t("unmute")
                : this.pc.t("mute")}
          title=${!this._hasAudio ? "No audio" : isMuted ? this.pc.t("unmute") : this.pc.t("mute")}
        >
          ${isMuted || !this._hasAudio ? volumeOffIcon(16) : volumeUpIcon(16)}
        </button>

        <div
          class=${classMap({
            "fw-volume-slider-wrapper": true,
            "fw-volume-slider-wrapper--expanded": this._expanded,
            "fw-volume-slider-wrapper--collapsed": !this._expanded,
        })}
        >
          <div
            class="slider"
            role="slider"
            aria-label=${this.pc.t("volume")}
            aria-valuemin="0"
            aria-valuemax="100"
            aria-valuenow=${Math.round(displayVolume * 100)}
            @pointerdown=${this._onSliderPointerDown}
          >
            <div class="slider-fill" style=${styleMap({ width: `${displayVolume * 100}%` })}></div>
            <div class="slider-thumb" style=${styleMap({ left: `${displayVolume * 100}%` })}></div>
          </div>
        </div>
      </div>
    `;
    }
};
FwVolumeControl.styles = [
    sharedStyles,
    css `
      :host {
        display: flex;
        align-items: center;
      }

      .slider {
        position: relative;
        width: 100%;
        height: 0.25rem;
        background: rgb(255 255 255 / 0.2);
        border-radius: 9999px;
        cursor: pointer;
        touch-action: none;
        user-select: none;
      }

      .slider-fill {
        position: absolute;
        top: 0;
        left: 0;
        height: 100%;
        border-radius: 9999px;
        background: hsl(var(--tn-fg));
      }

      .slider-thumb {
        position: absolute;
        top: 50%;
        width: 0.625rem;
        height: 0.625rem;
        border-radius: 9999px;
        background: hsl(var(--tn-fg));
        transform: translate(-50%, -50%);
        pointer-events: none;
      }
    `,
];
__decorate([
    property({ attribute: false })
], FwVolumeControl.prototype, "pc", void 0);
__decorate([
    state()
], FwVolumeControl.prototype, "_hovered", void 0);
__decorate([
    state()
], FwVolumeControl.prototype, "_focused", void 0);
__decorate([
    state()
], FwVolumeControl.prototype, "_dragging", void 0);
__decorate([
    state()
], FwVolumeControl.prototype, "_hasAudio", void 0);
FwVolumeControl = __decorate([
    customElement("fw-volume-control")
], FwVolumeControl);

export { FwVolumeControl };
//# sourceMappingURL=fw-volume-control.js.map
