import { isEFTemporal } from "../elements/EFTemporal.js";
import { isContextMixin } from "./ContextMixin.js";

//#region src/gui/Controllable.ts
function isControllable(value) {
	if (!value || typeof value !== "object") return false;
	if (isContextMixin(value)) return true;
	if (isEFTemporal(value)) return value.playbackController !== void 0;
	return false;
}
/**
* Determines the type of controllable target for subscription purposes.
*
* - "context-provider": Target is a ContextMixin (like EFPreview) that provides contexts
* - "direct-temporal": Target is a root temporal element with its own playbackController
* - "none": Target is not controllable (null, undefined, or nested temporal)
*/
function determineTargetType(target) {
	if (!target) return "none";
	if (isContextMixin(target)) return "context-provider";
	if (isEFTemporal(target)) {
		if (target.playbackController) return "direct-temporal";
	}
	return "none";
}
/**
* Creates a subscription to a direct temporal element's playback controller.
* Used when EFControls targets a temporal element directly (not wrapped in EFPreview).
*/
function createDirectTemporalSubscription(target, callbacks) {
	const controller = target.playbackController;
	callbacks.onPlayingChange(controller.playing);
	callbacks.onLoopChange(controller.loop);
	callbacks.onCurrentTimeMsChange(controller.currentTimeMs);
	callbacks.onDurationMsChange(target.durationMs);
	callbacks.onTargetTemporalChange(target);
	const listener = (event) => {
		switch (event.property) {
			case "playing":
				callbacks.onPlayingChange(event.value);
				break;
			case "loop":
				callbacks.onLoopChange(event.value);
				break;
			case "currentTimeMs":
				callbacks.onCurrentTimeMsChange(event.value);
				break;
		}
	};
	controller.addListener(listener);
	const durationObserver = new MutationObserver(() => {
		callbacks.onDurationMsChange(target.durationMs);
	});
	durationObserver.observe(target, {
		attributes: true,
		attributeFilter: [
			"duration",
			"trimstart",
			"trimend",
			"sourcein",
			"sourceout"
		],
		subtree: true
	});
	let lastKnownDuration = target.durationMs;
	let durationPollInterval = null;
	if (lastKnownDuration === 0) durationPollInterval = setInterval(() => {
		const currentDuration = target.durationMs;
		if (currentDuration !== lastKnownDuration) {
			lastKnownDuration = currentDuration;
			callbacks.onDurationMsChange(currentDuration);
			if (currentDuration > 0 && durationPollInterval) {
				clearInterval(durationPollInterval);
				durationPollInterval = null;
			}
		}
	}, 100);
	return { unsubscribe: () => {
		controller.removeListener(listener);
		durationObserver.disconnect();
		if (durationPollInterval) clearInterval(durationPollInterval);
	} };
}

//#endregion
export { createDirectTemporalSubscription, determineTargetType, isControllable };
//# sourceMappingURL=Controllable.js.map