import { context, propagation, trace } from "@opentelemetry/api";

//#region src/otel/tracingHelpers.ts
/**
* Global flag to enable/disable tracing.
* When false, all tracing functions become no-ops for zero overhead.
*/
let tracingEnabled = false;
/**
* Enable tracing globally. Call this during initialization if tracing is requested.
*/
function enableTracing() {
	tracingEnabled = true;
}
/**
* Check if tracing is currently enabled.
*/
function isTracingEnabled() {
	return tracingEnabled;
}
/**
* Frame-local span storage for rendering.
* Since rendering is single-threaded and sequential (one frame at a time),
* we store the active frame span directly and use it as parent for orphaned spans.
*/
let currentFrameSpan;
/**
* Set the current frame's span. Call this when starting a frame render.
* All spans created during this frame will use this as parent if
* Zone.js doesn't provide one via context.active()
*/
function setCurrentFrameSpan(span) {
	currentFrameSpan = span;
}
/**
* Clear the current frame span. Call this when a frame completes.
*/
function clearCurrentFrameSpan() {
	currentFrameSpan = void 0;
}
function extractParentContext(traceContext) {
	if (!traceContext) return context.active();
	try {
		return propagation.extract(context.active(), traceContext);
	} catch (_error) {
		return context.active();
	}
}
/**
* Wrapper that passes span context explicitly to the function
* Use this for operations that need to store or propagate context across boundaries
*/
async function withSpanAndContext(name, attributes, parentContext, fn) {
	if (!tracingEnabled) {
		const noopSpan = trace.getTracer("telecine-browser").startSpan(name);
		const result = await fn(noopSpan, parentContext || context.active());
		noopSpan.end();
		return result;
	}
	const tracer = trace.getTracer("telecine-browser");
	let ctx;
	if (parentContext) ctx = parentContext;
	else {
		const activeContext = context.active();
		if (trace.getSpan(activeContext)?.isRecording?.()) ctx = activeContext;
		else if (currentFrameSpan) ctx = trace.setSpan(context.active(), currentFrameSpan);
		else ctx = activeContext;
	}
	const span = tracer.startSpan(name, { attributes }, ctx);
	const spanContext = trace.setSpan(ctx, span);
	try {
		const result = await context.with(spanContext, async () => {
			return fn(span, spanContext);
		});
		span.end();
		return result;
	} catch (error) {
		span.recordException(error);
		span.end();
		throw error;
	}
}
function createSpan(name, attributes, parentContext) {
	const tracer = trace.getTracer("telecine-browser");
	const ctx = parentContext || context.active();
	return context.with(ctx, () => {
		const span = tracer.startSpan(name);
		if (attributes) span.setAttributes(attributes);
		return span;
	});
}
async function withSpan(name, attributes, parentContext, fn) {
	if (!tracingEnabled) {
		const noopSpan = trace.getTracer("telecine-browser").startSpan(name);
		const result = await fn(noopSpan);
		noopSpan.end();
		return result;
	}
	const tracer = trace.getTracer("telecine-browser");
	let ctx;
	if (parentContext) ctx = parentContext;
	else {
		const activeContext = context.active();
		if (trace.getSpan(activeContext)?.isRecording?.()) ctx = activeContext;
		else if (currentFrameSpan) ctx = trace.setSpan(context.active(), currentFrameSpan);
		else ctx = activeContext;
	}
	const span = tracer.startSpan(name, { attributes }, ctx);
	const spanContext = trace.setSpan(ctx, span);
	try {
		const result = await context.with(spanContext, async () => {
			return fn(span);
		});
		span.end();
		return result;
	} catch (error) {
		span.recordException(error);
		span.end();
		throw error;
	}
}
function withSpanSync(name, attributes, parentContext, fn) {
	if (!tracingEnabled) {
		const noopSpan = trace.getTracer("telecine-browser").startSpan(name);
		const result = fn(noopSpan);
		noopSpan.end();
		return result;
	}
	const span = createSpan(name, attributes, parentContext);
	const ctx = parentContext || context.active();
	try {
		const result = context.with(trace.setSpan(ctx, span), () => fn(span));
		span.end();
		return result;
	} catch (error) {
		span.recordException(error);
		span.end();
		throw error;
	}
}

//#endregion
export { clearCurrentFrameSpan, enableTracing, extractParentContext, isTracingEnabled, setCurrentFrameSpan, withSpan, withSpanAndContext, withSpanSync };
//# sourceMappingURL=tracingHelpers.js.map