import { deepGetTemporalElements, isEFTemporal } from "./EFTemporal.js";
const ANIMATION_PRECISION_OFFSET = Number.EPSILON;
const DEFAULT_ANIMATION_ITERATIONS = 1;
const PROGRESS_PROPERTY = "--ef-progress";
const DURATION_PROPERTY = "--ef-duration";
const TRANSITION_DURATION_PROPERTY = "--ef-transition-duration";
const TRANSITION_OUT_START_PROPERTY = "--ef-transition-out-start";
const TIMEGROUP_TAGNAME = "ef-timegroup";
/**
* Evaluates what the element's state should be based on the timeline
*/
const evaluateTemporalState = (element) => {
	const timelineTimeMs = (element.rootTimegroup ?? element).currentTimeMs;
	const progress = element.durationMs <= 0 ? 1 : Math.max(0, Math.min(1, element.currentTimeMs / element.durationMs));
	const isVisible = element.startTimeMs <= timelineTimeMs && element.endTimeMs > timelineTimeMs;
	return {
		progress,
		isVisible,
		timelineTimeMs
	};
};
/**
* Updates the visual state (CSS + display) to match temporal state
*/
const updateVisualState = (element, state) => {
	element.style.setProperty(PROGRESS_PROPERTY, `${state.progress * 100}%`);
	if (!state.isVisible) {
		if (element.style.display !== "none") element.style.display = "none";
		return;
	}
	if (element.style.display === "none") element.style.display = "";
	element.style.setProperty(DURATION_PROPERTY, `${element.durationMs}ms`);
	element.style.setProperty(TRANSITION_DURATION_PROPERTY, `${element.parentTimegroup?.overlapMs ?? 0}ms`);
	element.style.setProperty(TRANSITION_OUT_START_PROPERTY, `${element.durationMs - (element.parentTimegroup?.overlapMs ?? 0)}ms`);
};
/**
* Coordinates animations to match timeline
*/
const coordinateAnimations = (element) => {
	const animations = element.getAnimations({ subtree: true });
	for (const animation of animations) {
		if (animation.playState === "running") animation.pause();
		const effect = animation.effect;
		if (!(effect && effect instanceof KeyframeEffect)) continue;
		const target = effect.target;
		if (!target || target.closest(TIMEGROUP_TAGNAME) !== element) continue;
		const timeTarget = isEFTemporal(target) ? target : target.closest(TIMEGROUP_TAGNAME);
		if (!timeTarget) continue;
		const timing = effect.getTiming();
		const duration = Number(timing.duration) || 0;
		const delay = Number(timing.delay) || 0;
		const iterations = Number(timing.iterations) || DEFAULT_ANIMATION_ITERATIONS;
		if (duration <= 0) {
			animation.currentTime = 0;
			continue;
		}
		const currentTime = timeTarget.ownCurrentTimeMs ?? 0;
		if (currentTime < delay) {
			animation.currentTime = 0;
			continue;
		}
		const adjustedTime = currentTime - delay;
		const currentIteration = Math.floor(adjustedTime / duration);
		const currentIterationTime = adjustedTime % duration;
		if (currentIteration >= iterations) animation.currentTime = duration - ANIMATION_PRECISION_OFFSET;
		else animation.currentTime = Math.min(currentIterationTime, duration - ANIMATION_PRECISION_OFFSET) + delay;
	}
};
/**
* Main function: synchronizes DOM element with timeline
*/
const updateAnimations = (element) => {
	const temporalState = evaluateTemporalState(element);
	deepGetTemporalElements(element).forEach((temporalElement) => {
		const temporalState$1 = evaluateTemporalState(temporalElement);
		updateVisualState(temporalElement, temporalState$1);
	});
	updateVisualState(element, temporalState);
	if (temporalState.isVisible) coordinateAnimations(element);
};
export { evaluateTemporalState, updateAnimations };
