import type { Observable } from 'rxjs';
import { Subject } from 'rxjs';
import type { AddSpanToRecordingEvent, DefinitionModifiedEvent, RequiredSpanSeenEvent, StateTransitionEvent } from './debugTypes';
import { type CPUIdleLongTaskProcessor, type PerformanceEntryLike } from './firstCPUIdle';
import { type SpanMatcherFn } from './matchSpan';
import type { SpanAndAnnotation, SpanAnnotationRecord } from './spanAnnotationTypes';
import type { ActiveTraceConfig, DraftTraceInput, Span } from './spanTypes';
import type { TraceRecording } from './traceRecordingTypes';
import type { CompleteTraceDefinition, DraftTraceContext, RelationSchemasBase, TraceContext, TraceDefinitionModifications, TraceInterruptionReason, TraceManagerUtilities, TraceModifications, TransitionDraftOptions } from './types';
import type { DistributiveOmit, StateHandlerPayloads } from './typeUtils';
declare const INITIAL_STATE = "draft";
type InitialTraceState = typeof INITIAL_STATE;
export type NonTerminalTraceStates = InitialTraceState | 'active' | 'debouncing' | 'waiting-for-interactive';
export declare const TERMINAL_STATES: readonly ["interrupted", "complete"];
type TerminalTraceStates = (typeof TERMINAL_STATES)[number];
export type TraceStates = NonTerminalTraceStates | TerminalTraceStates;
export declare const isTerminalState: (state: TraceStates) => state is TerminalTraceStates;
interface OnEnterActive {
    transitionToState: 'active';
    transitionFromState: NonTerminalTraceStates;
}
interface OnEnterInterrupted<RelationSchemasT> {
    transitionToState: 'interrupted';
    transitionFromState: NonTerminalTraceStates;
    interruptionReason: TraceInterruptionReason;
    lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
}
interface OnEnterComplete<RelationSchemasT> {
    transitionToState: 'complete';
    transitionFromState: NonTerminalTraceStates;
    interruptionReason?: TraceInterruptionReason;
    cpuIdleSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
    completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
    lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
    lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
}
export type FinalTransition<RelationSchemasT> = OnEnterInterrupted<RelationSchemasT> | OnEnterComplete<RelationSchemasT>;
interface OnEnterWaitingForInteractive {
    transitionToState: 'waiting-for-interactive';
    transitionFromState: NonTerminalTraceStates;
}
interface OnEnterDebouncing {
    transitionToState: 'debouncing';
    transitionFromState: NonTerminalTraceStates;
}
export type OnEnterStatePayload<RelationSchemasT> = OnEnterActive | OnEnterInterrupted<RelationSchemasT> | OnEnterComplete<RelationSchemasT> | OnEnterDebouncing | OnEnterWaitingForInteractive;
export type Transition<RelationSchemasT> = DistributiveOmit<OnEnterStatePayload<RelationSchemasT>, 'transitionFromState'>;
export type States<SelectedRelationNameT extends keyof RelationSchemasT, RelationSchemasT, VariantsT extends string> = TraceStateMachine<SelectedRelationNameT, RelationSchemasT, VariantsT>['states'];
interface TraceStateMachineSideEffectHandlers<RelationSchemasT> {
    readonly addSpanToRecording: (spanAndAnnotation: SpanAndAnnotation<RelationSchemasT>) => void;
    readonly prepareAndEmitRecording: (transition: OnEnterStatePayload<RelationSchemasT>) => void;
}
type EntryType<RelationSchemasT> = PerformanceEntryLike & {
    entry: SpanAndAnnotation<RelationSchemasT>;
};
interface StateMachineContext<SelectedRelationNameT extends keyof RelationSchemasT, RelationSchemasT, VariantsT extends string> extends DraftTraceContext<SelectedRelationNameT, RelationSchemasT, VariantsT> {
    sideEffectFns: TraceStateMachineSideEffectHandlers<RelationSchemasT>;
    eventSubjects: {
        'state-transition': Subject<StateTransitionEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
        'required-span-seen': Subject<RequiredSpanSeenEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
        'add-span-to-recording': Subject<AddSpanToRecordingEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
        'definition-modified': Subject<DefinitionModifiedEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    };
}
type DeadlineType = 'global' | 'debounce' | 'interactive' | 'next-quiet-window';
export declare class TraceStateMachine<SelectedRelationNameT extends keyof RelationSchemasT, RelationSchemasT, const VariantsT extends string> {
    #private;
    constructor(context: StateMachineContext<SelectedRelationNameT, RelationSchemasT, VariantsT>);
    readonly successfullyMatchedRequiredSpanMatchers: Set<SpanMatcherFn<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    get sideEffectFns(): TraceStateMachineSideEffectHandlers<RelationSchemasT>;
    currentState: TraceStates;
    /** the span that ended at the furthest point in time */
    lastRelevant: SpanAndAnnotation<RelationSchemasT> | undefined;
    lastRequiredSpan: SpanAndAnnotation<RelationSchemasT> | undefined;
    /** it is set once the LRS value is established */
    completeSpan: SpanAndAnnotation<RelationSchemasT> | undefined;
    cpuIdleLongTaskProcessor: CPUIdleLongTaskProcessor<EntryType<RelationSchemasT>> | undefined;
    nextDeadlineRef: ReturnType<typeof setTimeout> | undefined;
    setDeadline(deadlineType: Exclude<DeadlineType, 'global'>, deadlineEpoch: number): void;
    setGlobalDeadline(deadline: number): void;
    clearDeadline(): void;
    /**
     * while debouncing, we need to buffer any spans that come in so they can be re-processed
     * once we transition to the 'waiting-for-interactive' state
     * otherwise we might miss out on spans that are relevant to calculating the interactive
     *
     * if we have long tasks before FMP, we want to use them as a potential grouping post FMP.
     */
    debouncingSpanBuffer: SpanAndAnnotation<RelationSchemasT>[];
    readonly states: {
        draft: {
            onEnterState: () => void;
            onMakeActive: () => {
                transitionToState: "active";
            };
            onProcessSpan: (spanAndAnnotation: SpanAndAnnotation<RelationSchemasT>) => {
                transitionToState: "interrupted";
                interruptionReason: "timeout";
                lastRelevantSpanAndAnnotation: undefined;
            } | {
                transitionToState: "interrupted";
                interruptionReason: "matched-on-interrupt" | "matched-on-required-span-with-error";
                lastRelevantSpanAndAnnotation: undefined;
            } | undefined;
            onInterrupt: (reason: TraceInterruptionReason) => {
                transitionToState: "interrupted";
                interruptionReason: TraceInterruptionReason;
                lastRelevantSpanAndAnnotation: undefined;
            };
            onDeadline: (deadlineType: DeadlineType) => {
                transitionToState: "interrupted";
                interruptionReason: "timeout";
                lastRelevantSpanAndAnnotation: undefined;
            } | undefined;
        };
        active: {
            onEnterState: (_transition: OnEnterActive) => Transition<RelationSchemasT> | undefined;
            onProcessSpan: (spanAndAnnotation: SpanAndAnnotation<RelationSchemasT>) => {
                transitionToState: "interrupted";
                interruptionReason: "timeout";
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            } | {
                transitionToState: "interrupted";
                interruptionReason: "matched-on-interrupt" | "matched-on-required-span-with-error";
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            } | {
                transitionToState: "debouncing";
                interruptionReason?: undefined;
                lastRelevantSpanAndAnnotation?: undefined;
            } | undefined;
            onInterrupt: (reason: TraceInterruptionReason) => {
                transitionToState: "interrupted";
                interruptionReason: TraceInterruptionReason;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            };
            onDeadline: (deadlineType: DeadlineType) => {
                transitionToState: "interrupted";
                interruptionReason: "timeout";
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            } | undefined;
        };
        debouncing: {
            onEnterState: (_payload: OnEnterDebouncing) => {
                transitionToState: "interrupted";
                interruptionReason: "invalid-state-transition";
                lastRelevantSpanAndAnnotation: undefined;
            } | {
                transitionToState: "waiting-for-interactive";
                interruptionReason?: undefined;
                lastRelevantSpanAndAnnotation?: undefined;
            } | undefined;
            onDeadline: (deadlineType: DeadlineType) => {
                transitionToState: "interrupted";
                interruptionReason: "timeout";
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            } | {
                transitionToState: "waiting-for-interactive";
                interruptionReason?: undefined;
                lastRelevantSpanAndAnnotation?: undefined;
            } | undefined;
            onProcessSpan: (spanAndAnnotation: SpanAndAnnotation<RelationSchemasT>) => {
                transitionToState: "interrupted";
                interruptionReason: "timeout";
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            } | {
                transitionToState: "waiting-for-interactive";
                interruptionReason?: undefined;
                lastRelevantSpanAndAnnotation?: undefined;
            } | {
                transitionToState: "interrupted";
                interruptionReason: "idle-component-no-longer-idle";
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            } | undefined;
            onInterrupt: (reason: TraceInterruptionReason) => {
                transitionToState: "interrupted";
                interruptionReason: TraceInterruptionReason;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
            };
        };
        'waiting-for-interactive': {
            onEnterState: (_payload: OnEnterWaitingForInteractive) => Transition<RelationSchemasT> | undefined;
            onDeadline: (deadlineType: DeadlineType) => {
                transitionToState: "complete";
                interruptionReason: "timeout";
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: undefined;
            } | {
                transitionToState: "complete";
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT>;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                interruptionReason?: undefined;
            } | undefined;
            onProcessSpan: (spanAndAnnotation: SpanAndAnnotation<RelationSchemasT>) => {
                transitionToState: "complete";
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT>;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                interruptionReason?: undefined;
            } | {
                transitionToState: "complete";
                interruptionReason: "timeout";
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: undefined;
            } | {
                transitionToState: "complete";
                interruptionReason: "waiting-for-interactive-timeout";
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: undefined;
            } | {
                transitionToState: "complete";
                interruptionReason: "matched-on-interrupt" | "matched-on-required-span-with-error";
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: undefined;
            } | undefined;
            onInterrupt: (reason: TraceInterruptionReason) => {
                transitionToState: "complete";
                interruptionReason: TraceInterruptionReason;
                lastRequiredSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                completeSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                lastRelevantSpanAndAnnotation: SpanAndAnnotation<RelationSchemasT> | undefined;
                cpuIdleSpanAndAnnotation: undefined;
            };
        };
        interrupted: {
            onEnterState: (transition: OnEnterInterrupted<RelationSchemasT>) => void;
        };
        complete: {
            onEnterState: (transition: OnEnterComplete<RelationSchemasT>) => void;
        };
    };
    /**
     * @returns the last OnEnterState event if a transition was made
     */
    emit<EventName extends keyof StateHandlerPayloads<SelectedRelationNameT, RelationSchemasT, VariantsT>>(event: EventName, payload: StateHandlerPayloads<SelectedRelationNameT, RelationSchemasT, VariantsT>[EventName]): OnEnterStatePayload<RelationSchemasT> | undefined;
}
export declare class Trace<const SelectedRelationNameT extends keyof RelationSchemasT, const RelationSchemasT extends RelationSchemasBase<RelationSchemasT>, const VariantsT extends string> implements TraceContext<SelectedRelationNameT, RelationSchemasT, VariantsT> {
    readonly sourceDefinition: CompleteTraceDefinition<SelectedRelationNameT, RelationSchemasT, VariantsT>;
    /** the final, mutable definition of this specific trace */
    definition: CompleteTraceDefinition<SelectedRelationNameT, RelationSchemasT, VariantsT>;
    wasActivated: boolean;
    get activeInput(): ActiveTraceConfig<SelectedRelationNameT, RelationSchemasT, VariantsT>;
    set activeInput(value: ActiveTraceConfig<SelectedRelationNameT, RelationSchemasT, VariantsT>);
    input: DraftTraceInput<RelationSchemasT[SelectedRelationNameT], VariantsT>;
    readonly traceUtilities: TraceManagerUtilities<RelationSchemasT>;
    get isDraft(): boolean;
    recordedItems: Set<SpanAndAnnotation<RelationSchemasT>>;
    occurrenceCounters: Map<string, number>;
    processedPerformanceEntries: WeakMap<PerformanceEntry, SpanAndAnnotation<RelationSchemasT>>;
    persistedDefinitionModifications: Set<TraceDefinitionModifications<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    readonly recordedItemsByLabel: {
        [label: string]: SpanAndAnnotation<RelationSchemasT>[];
    };
    stateMachine: TraceStateMachine<SelectedRelationNameT, RelationSchemasT, VariantsT>;
    eventSubjects: {
        'state-transition': Subject<StateTransitionEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
        'required-span-seen': Subject<RequiredSpanSeenEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
        'add-span-to-recording': Subject<AddSpanToRecordingEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
        'definition-modified': Subject<DefinitionModifiedEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    };
    when(event: 'state-transition'): Observable<StateTransitionEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    when(event: 'required-span-seen'): Observable<RequiredSpanSeenEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    when(event: 'add-span-to-recording'): Observable<AddSpanToRecordingEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    when(event: 'definition-modified'): Observable<DefinitionModifiedEvent<SelectedRelationNameT, RelationSchemasT, VariantsT>>;
    constructor(data: {
        definition: CompleteTraceDefinition<SelectedRelationNameT, RelationSchemasT, VariantsT>;
        input: DraftTraceInput<RelationSchemasT[SelectedRelationNameT], VariantsT>;
        definitionModifications?: TraceDefinitionModifications<SelectedRelationNameT, RelationSchemasT, VariantsT>;
        traceUtilities: TraceManagerUtilities<RelationSchemasT>;
    } | {
        importFrom: Trace<SelectedRelationNameT, RelationSchemasT, VariantsT>;
        definitionModifications: TraceDefinitionModifications<SelectedRelationNameT, RelationSchemasT, VariantsT>;
    });
    /**
     * all requiredSpans implicitly interrupt the trace if they error, unless explicitly ignored
     */
    mapRequiredSpanMatchersToInterruptOnMatchers(requiredSpans: readonly SpanMatcherFn<SelectedRelationNameT, RelationSchemasT, VariantsT>[]): readonly SpanMatcherFn<SelectedRelationNameT, RelationSchemasT, VariantsT>[];
    sideEffectFns: TraceStateMachineSideEffectHandlers<RelationSchemasT>;
    onEnd(traceRecording: TraceRecording<SelectedRelationNameT, RelationSchemasT>): void;
    interrupt(reason: TraceInterruptionReason): void;
    transitionDraftToActive(inputAndDefinitionModifications: TraceModifications<SelectedRelationNameT, RelationSchemasT, VariantsT>, { previouslyActivatedBehavior, invalidRelatedToBehavior, }?: TransitionDraftOptions): void;
    /**
     * The additions to the definition may come from either the variant at transition from draft to active
     * @param definitionModifications
     */
    private applyDefinitionModifications;
    /**
     * This is used for importing spans when recreating a Trace from another Trace
     * if the definition was modified
     */
    private replayItems;
    processSpan(span: Span<RelationSchemasT>): SpanAnnotationRecord | undefined;
    private getSpanLabels;
}
export type AllPossibleTraces<RelationSchemasT extends RelationSchemasBase<RelationSchemasT>> = Trace<any, RelationSchemasT, any>;
export {};
