import type { ReactNode } from "react";
import type { NavigationLocation, NavigateOptions, TrackedActionState, InflightAction, RscMetadata, HandleData } from "./types.js";
/**
 * Phase of a navigation operation
 */
export type NavigationPhase = "fetching" | "streaming";
/**
 * Phase of an action operation
 */
export type ActionPhase = "fetching" | "streaming" | "settling";
/**
 * Entry tracking an in-flight navigation
 */
export interface NavigationEntry {
    url: string;
    abort: AbortController;
    phase: NavigationPhase;
    startedAt: number;
    options?: NavigateOptions & {
        skipLoadingState?: boolean;
    };
}
/**
 * Entry tracking an in-flight action
 */
export interface ActionEntry {
    /** Unique instance ID for this action invocation */
    id: string;
    /** Server action function ID (normalized name like "addToCart") */
    actionId: string;
    /** Abort controller for this action */
    abort: AbortController;
    /** Current phase of the action */
    phase: ActionPhase;
    /** Action arguments */
    payload: unknown[];
    /** Result from action (set on completion) */
    result?: unknown;
    /** Error from action (set on failure) */
    error?: unknown;
    /** Segment IDs that were revalidated by this action */
    revalidatedSegments: string[];
    /** Timestamp when action started */
    startedAt: number;
    /** Whether action processing is complete (may still be streaming) */
    completed?: boolean;
}
/**
 * Derived navigation state (computed from source of truth)
 */
export interface DerivedNavigationState {
    /** Navigation lifecycle state */
    state: "idle" | "loading";
    /** Whether any operation is streaming */
    isStreaming: boolean;
    /** Current committed location */
    location: NavigationLocation;
    /** URL being navigated to (null if idle) */
    pendingUrl: string | null;
    /** List of inflight actions (for compatibility) */
    inflightActions: InflightAction[];
}
/**
 * Callback for UI updates when root should re-render
 */
export type UpdateCallback = (update: {
    root: ReactNode | Promise<ReactNode>;
    metadata: RscMetadata;
}) => void;
/**
 * State change listener
 */
export type StateListener = () => void;
/**
 * Action state listener
 */
export type ActionStateListener = (state: TrackedActionState) => void;
/**
 * Handle state listener
 */
export type HandleListener = () => void;
/**
 * Internal handle state stored in controller
 */
export interface HandleState {
    data: HandleData;
    segmentOrder: string[];
}
/**
 * Token for tracking an active stream
 * Call end() when the stream completes
 */
export interface StreamingToken {
    /** End this streaming operation */
    end(): void;
}
/**
 * Result from starting a navigation
 * Implements Disposable for use with `using` keyword
 */
export interface NavigationHandle extends Disposable {
    /** Abort controller for this navigation */
    abort: AbortController;
    /** Signal for this navigation */
    signal: AbortSignal;
    /** Start streaming and get a token to end it later */
    startStreaming(): StreamingToken;
    /** Complete the navigation successfully */
    complete(location: NavigationLocation): void;
    /** Whether navigation was completed successfully */
    readonly completed: boolean;
}
/**
 * Result from starting an action
 * Implements Disposable for use with `using` keyword
 */
export interface ActionHandle extends Disposable {
    /** Unique instance ID */
    id: string;
    /** Abort controller for this action */
    abort: AbortController;
    /** Signal for this action */
    signal: AbortSignal;
    /** Start streaming and get a token to end it later */
    startStreaming(): StreamingToken;
    /** Record segments that were revalidated */
    recordRevalidatedSegments(segmentIds: string[]): void;
    /** Complete the action with result */
    complete(result?: unknown): void;
    /** Fail the action with error */
    fail(error: unknown): void;
    /** Whether action was completed (success or failure) */
    readonly settled: boolean;
    /** Check if any concurrent actions were started */
    hadConcurrentActions: boolean;
    /** Get segments to consolidate (only valid when this is the last action) */
    getConsolidationSegments(): string[] | null;
    /** Clear consolidation tracking */
    clearConsolidation(): void;
}
/**
 * Event controller interface
 */
export interface EventController {
    startNavigation(url: string, options?: NavigateOptions & {
        skipLoadingState?: boolean;
    }): NavigationHandle;
    abortNavigation(): void;
    startAction(actionId: string, args: unknown[]): ActionHandle;
    abortAllActions(): void;
    getState(): DerivedNavigationState;
    getActionState(actionId: string): TrackedActionState;
    setLocation(location: NavigationLocation): void;
    subscribe(listener: StateListener): () => void;
    subscribeToAction(actionId: string, listener: ActionStateListener): () => void;
    subscribeToHandles(listener: HandleListener): () => void;
    setHandleData(data: HandleData, matched?: string[], isPartial?: boolean): void;
    getHandleState(): HandleState;
    getCurrentNavigation(): NavigationEntry | null;
    getInflightActions(): Map<string, ActionEntry>;
}
/**
 * Configuration for creating an event controller
 */
export interface EventControllerConfig {
    initialLocation?: NavigationLocation;
}
/**
 * Create an event controller for managing navigation and action state
 *
 * The controller uses a reactive model where:
 * - Source of truth: currentNavigation, inflightActions, location
 * - Derived state: navState, isStreaming computed from source
 *
 * Navigation uses switchMap semantics (new nav cancels previous).
 * Actions use mergeMap semantics (all run concurrently, consolidate at end).
 */
export declare function createEventController(config?: EventControllerConfig): EventController;
/**
 * Initialize the global event controller
 */
export declare function initEventController(config?: EventControllerConfig): EventController;
/**
 * Get the global event controller
 */
export declare function getEventController(): EventController;
/**
 * Reset the controller instance (for testing)
 */
export declare function resetEventController(): void;
//# sourceMappingURL=event-controller.d.ts.map