import { UrlGenerator } from "../transcoding/utils/UrlGenerator.js";
import { makeMediaEngineTask } from "./EFMedia/tasks/makeMediaEngineTask.js";
import { makeAudioBufferTask } from "./EFMedia/audioTasks/makeAudioBufferTask.js";
import { makeAudioFrequencyAnalysisTask } from "./EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js";
import { makeAudioInitSegmentFetchTask } from "./EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js";
import { makeAudioInputTask } from "./EFMedia/audioTasks/makeAudioInputTask.js";
import { makeAudioSeekTask } from "./EFMedia/audioTasks/makeAudioSeekTask.js";
import { makeAudioSegmentFetchTask } from "./EFMedia/audioTasks/makeAudioSegmentFetchTask.js";
import { makeAudioSegmentIdTask } from "./EFMedia/audioTasks/makeAudioSegmentIdTask.js";
import { makeAudioTimeDomainAnalysisTask } from "./EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js";
import { fetchAudioSpanningTime } from "./EFMedia/shared/AudioSpanUtils.js";
import { EFSourceMixin } from "./EFSourceMixin.js";
import { EFTemporal } from "./EFTemporal.js";
import { FetchMixin } from "./FetchMixin.js";
import { EFTargetable } from "./TargetController.js";
import { updateAnimations } from "./updateAnimations.js";
import { LitElement, css } from "lit";
import { property, state } from "lit/decorators.js";
import _decorate from "@oxc-project/runtime/helpers/decorate";
const freqWeightsCache = /* @__PURE__ */ new Map();
var IgnorableError = class extends Error {};
const deepGetMediaElements = (element, medias = []) => {
	for (const child of Array.from(element.children)) if (child instanceof EFMedia) medias.push(child);
	else deepGetMediaElements(child, medias);
	return medias;
};
var EFMedia = class extends EFTargetable(EFSourceMixin(EFTemporal(FetchMixin(LitElement)), { assetType: "isobmff_files" })) {
	constructor(..._args) {
		super(..._args);
		this.currentTimeMs = 0;
		this.audioBufferDurationMs = 3e4;
		this.maxAudioBufferFetches = 2;
		this.enableAudioBuffering = true;
		this.mute = false;
		this.fftSize = 128;
		this.fftDecay = 8;
		this.fftGain = 3;
		this.interpolateFrequencies = false;
		this.mediaEngineTask = makeMediaEngineTask(this);
		this.audioSegmentIdTask = makeAudioSegmentIdTask(this);
		this.audioInitSegmentFetchTask = makeAudioInitSegmentFetchTask(this);
		this.audioSegmentFetchTask = makeAudioSegmentFetchTask(this);
		this.audioInputTask = makeAudioInputTask(this);
		this.audioSeekTask = makeAudioSeekTask(this);
		this.audioBufferTask = makeAudioBufferTask(this);
		this.byteTimeDomainTask = makeAudioTimeDomainAnalysisTask(this);
		this.frequencyDataTask = makeAudioFrequencyAnalysisTask(this);
		this.assetId = null;
		this._desiredSeekTimeMs = 0;
	}
	static {
		this.VIDEO_SAMPLE_BUFFER_SIZE = 30;
	}
	static {
		this.AUDIO_SAMPLE_BUFFER_SIZE = 120;
	}
	static get observedAttributes() {
		const parentAttributes = super.observedAttributes || [];
		return [
			...parentAttributes,
			"mute",
			"fft-size",
			"fft-decay",
			"fft-gain",
			"interpolate-frequencies",
			"asset-id",
			"audio-buffer-duration",
			"max-audio-buffer-fetches",
			"enable-audio-buffering"
		];
	}
	static {
		this.styles = [css`
      :host {
        display: block;
        position: relative;
        overflow: hidden;
      }
    `];
	}
	get FREQ_WEIGHTS() {
		if (freqWeightsCache.has(this.fftSize)) return freqWeightsCache.get(this.fftSize);
		const weights = new Float32Array(this.fftSize / 2).map((_, i) => {
			const frequency = i * 48e3 / this.fftSize;
			if (frequency < 60) return .3;
			if (frequency < 250) return .4;
			if (frequency < 500) return .6;
			if (frequency < 2e3) return .8;
			if (frequency < 4e3) return 1.2;
			if (frequency < 8e3) return 1.6;
			return 2;
		});
		freqWeightsCache.set(this.fftSize, weights);
		return weights;
	}
	get shouldInterpolateFrequencies() {
		return this.interpolateFrequencies;
	}
	get urlGenerator() {
		return new UrlGenerator(() => this.apiHost ?? "");
	}
	get intrinsicDurationMs() {
		return this.mediaEngineTask.value?.durationMs ?? 0;
	}
	updated(changedProperties) {
		super.updated(changedProperties);
		const newCurrentSourceTimeMs = this.currentSourceTimeMs;
		if (newCurrentSourceTimeMs !== this.desiredSeekTimeMs) this.executeSeek(newCurrentSourceTimeMs);
		if (changedProperties.has("ownCurrentTimeMs")) this.executeSeek(this.currentSourceTimeMs);
		if (changedProperties.has("currentTime") || changedProperties.has("ownCurrentTimeMs")) updateAnimations(this);
	}
	get hasOwnDuration() {
		return true;
	}
	get desiredSeekTimeMs() {
		return this._desiredSeekTimeMs;
	}
	set desiredSeekTimeMs(value) {
		if (this._desiredSeekTimeMs !== value) this._desiredSeekTimeMs = value;
	}
	async executeSeek(seekToMs) {
		this.desiredSeekTimeMs = seekToMs;
	}
	/**
	* Main integration method for EFTimegroup audio playback
	* Now powered by clean, testable utility functions
	*/
	async fetchAudioSpanningTime(fromMs, toMs, signal = new AbortController().signal) {
		return fetchAudioSpanningTime(this, fromMs, toMs, signal);
	}
	/**
	* Check if an audio segment is cached in the unified buffer system
	* Now uses the same caching approach as video for consistency
	*/
	getCachedAudioSegment(segmentId) {
		return this.audioBufferTask.value?.cachedSegments.has(segmentId) ?? false;
	}
	/**
	* Get cached audio segments from the unified buffer system
	* Now uses the same caching approach as video for consistency
	*/
	getCachedAudioSegments(segmentIds) {
		const bufferState = this.audioBufferTask.value;
		if (!bufferState) return /* @__PURE__ */ new Set();
		return new Set(segmentIds.filter((id) => bufferState.cachedSegments.has(id)));
	}
};
_decorate([property({ type: Number })], EFMedia.prototype, "currentTimeMs", void 0);
_decorate([property({
	type: Number,
	attribute: "audio-buffer-duration"
})], EFMedia.prototype, "audioBufferDurationMs", void 0);
_decorate([property({
	type: Number,
	attribute: "max-audio-buffer-fetches"
})], EFMedia.prototype, "maxAudioBufferFetches", void 0);
_decorate([property({
	type: Boolean,
	attribute: "enable-audio-buffering"
})], EFMedia.prototype, "enableAudioBuffering", void 0);
_decorate([property({
	type: Boolean,
	attribute: "mute",
	reflect: true
})], EFMedia.prototype, "mute", void 0);
_decorate([property({
	type: Number,
	attribute: "fft-size",
	reflect: true
})], EFMedia.prototype, "fftSize", void 0);
_decorate([property({
	type: Number,
	attribute: "fft-decay",
	reflect: true
})], EFMedia.prototype, "fftDecay", void 0);
_decorate([property({
	type: Number,
	attribute: "fft-gain",
	reflect: true
})], EFMedia.prototype, "fftGain", void 0);
_decorate([property({
	type: Boolean,
	attribute: "interpolate-frequencies",
	reflect: true
})], EFMedia.prototype, "interpolateFrequencies", void 0);
_decorate([property({
	type: String,
	attribute: "asset-id",
	reflect: true
})], EFMedia.prototype, "assetId", void 0);
_decorate([state()], EFMedia.prototype, "_desiredSeekTimeMs", void 0);
export { EFMedia, IgnorableError, deepGetMediaElements };
