/**
* Async version of computeSegmentRange for when computeSegmentId is async
*/
const computeSegmentRangeAsync = async (startTimeMs, endTimeMs, durationMs, rendition, computeSegmentId) => {
	const segments = [];
	const segmentDurationMs = rendition.segmentDurationMs || 1e3;
	const startSegmentIndex = Math.floor(startTimeMs / segmentDurationMs);
	const endSegmentIndex = Math.floor(Math.min(endTimeMs, durationMs) / segmentDurationMs);
	for (let i = startSegmentIndex; i <= endSegmentIndex; i++) {
		const timeMs = i * segmentDurationMs;
		if (timeMs < durationMs) {
			const segmentId = await computeSegmentId(timeMs, rendition);
			if (segmentId !== void 0) segments.push(segmentId);
		}
	}
	return segments.filter((id, index, arr) => arr.indexOf(id) === index);
};
/**
* Compute buffer queue based on desired segments and what we've already requested
* Pure function - determines what new segments should be prefetched
*/
const computeBufferQueue = (desiredSegments, requestedSegments) => {
	return desiredSegments.filter((segmentId) => !requestedSegments.has(segmentId));
};
/**
* Core media buffering orchestration logic - prefetch only, no data storage
* Integrates with BaseMediaEngine's existing caching and request deduplication
*/
const manageMediaBuffer = async (seekTimeMs, config, currentState, durationMs, signal, deps) => {
	if (!config.enableBuffering) return currentState;
	const rendition = await deps.getRendition();
	const endTimeMs = seekTimeMs + config.bufferDurationMs;
	const desiredSegments = await computeSegmentRangeAsync(seekTimeMs, endTimeMs, durationMs, rendition, deps.computeSegmentId);
	const uncachedSegments = desiredSegments.filter((segmentId) => !deps.isSegmentCached(segmentId, rendition));
	const newQueue = computeBufferQueue(uncachedSegments, currentState.requestedSegments);
	const newRequestedSegments = new Set(currentState.requestedSegments);
	const newActiveRequests = new Set(currentState.activeRequests);
	const remainingQueue = [...newQueue];
	const startNextSegment = () => {
		if (newActiveRequests.size >= config.maxParallelFetches || remainingQueue.length === 0 || signal.aborted) return;
		const nextSegmentId = remainingQueue.shift();
		if (nextSegmentId === void 0) return;
		if (newRequestedSegments.has(nextSegmentId) || deps.isSegmentCached(nextSegmentId, rendition)) {
			startNextSegment();
			return;
		}
		newRequestedSegments.add(nextSegmentId);
		newActiveRequests.add(nextSegmentId);
		deps.prefetchSegment(nextSegmentId, rendition).then(() => {
			if (signal.aborted) return;
			newActiveRequests.delete(nextSegmentId);
			if (config.enableContinuousBuffering ?? true) startNextSegment();
		}).catch((error) => {
			if (signal.aborted) return;
			newActiveRequests.delete(nextSegmentId);
			deps.logError(`Failed to prefetch segment ${nextSegmentId}`, error);
			if (config.enableContinuousBuffering ?? true) startNextSegment();
		});
	};
	const initialBatchSize = Math.min(config.maxParallelFetches, newQueue.length);
	for (let i = 0; i < initialBatchSize; i++) startNextSegment();
	return {
		currentSeekTimeMs: seekTimeMs,
		requestedSegments: newRequestedSegments,
		activeRequests: newActiveRequests,
		requestQueue: remainingQueue
	};
};
export { manageMediaBuffer };
