/**
 * Section runtime engine — public facade (M7 — Variant C, layered).
 *
 * The facade is the narrow, stable entry point hosts use to mount,
 * drive, and dispose a section runtime. It composes three layers
 * introduced in earlier M7 PRs:
 *
 *   - the **registry** (`RuntimeRegistry`) — registered item/passage
 *     shells in document order, used for canonical-id lookup;
 *   - the **adapter** (`SectionEngineAdapter`) — single I/O seam over
 *     the pure FSM core, fanning outputs to the DOM, framework-error
 *     bus, instrumentation hook, and host subscribers;
 *   - the **resolver** (`resolveSectionEngineRuntimeState`) — the
 *     toolkit-side resolution helper that produces the effective
 *     runtime + tools snapshot a host feeds to the FSM core.
 *
 * The facade exposes an engine-side surface for stage/lifecycle inputs and a
 * controller-facing surface for item registration, session updates, and host
 * controller commands:
 *
 *   1. The **engine-side** surface (`attachHost`, `dispatchInput`,
 *      `subscribe`, `getState`, `getEffectiveRuntime`,
 *      `setInstrumentationHook`). This is what the kernel and the
 *      `pie-assessment-toolkit` CE will switch onto in M7 PR 5 and
 *      PR 6. Construction is lazy: `attachHost(...)` builds the
 *      adapter on first call, with the supplied host element,
 *      framework-error bus, and (optional) coordinator. After
 *      construction, host re-attachments (e.g. cohort change with a
 *      new layout shell) update the adapter's host element via
 *      `setHost(...)`.
 *
 *   2. The **controller-side** surface (`initialize`,
 *      `register`, `unregister`, `handleContent*`, `updateItemSession`,
 *      `navigateToItem`, `persist`, `hydrate`, `dispose`). The
 *      `PieAssessmentToolkit.svelte` CE drives section-controller and
 *      item-shell events through this surface.
 *
 * The two surfaces share `RuntimeRegistry` and the resolved
 * `SectionControllerHandle`.
 */
import type { ToolkitCoordinator } from "../services/ToolkitCoordinator.js";
import type { FrameworkErrorReporter } from "../services/framework-error-bus.js";
import type { SectionControllerEvent, SectionControllerHandle } from "../services/section-controller-types.js";
import { type SectionEngineAdapterOptions } from "./adapter/SectionEngineAdapter.js";
import type { InstrumentationHook } from "./adapter/instrumentation-bridge.js";
import type { EngineOutputListener } from "./adapter/subscriber-fanout.js";
import type { SectionEngineInput } from "./core/engine-input.js";
import type { SectionEngineOutput } from "./core/engine-output.js";
import { type EffectiveRuntime, type RuntimeInputs } from "./core/engine-resolver.js";
import { type SectionEngineState } from "./core/engine-state.js";
import type { RuntimeRegistrationDetail } from "./registration-events.js";
import { RuntimeRegistry } from "./RuntimeRegistry.js";
/**
 * Structural view of the resolved section controller, widened with the
 * extra methods the toolkit's runtime CE calls directly. Optional so
 * stub controllers used in tests do not need every entry point.
 */
interface RuntimeController extends SectionControllerHandle {
    getCompositionModel?: () => unknown;
    getCanonicalItemId?: (itemId: string) => string;
    handleContentLoaded?: (args: {
        itemId: string;
        canonicalItemId?: string;
        contentKind?: string;
        detail?: unknown;
        timestamp?: number;
    }) => void;
    handleContentRegistered?: (args: {
        itemId: string;
        canonicalItemId?: string;
        contentKind?: string;
    }) => void;
    handleContentUnregistered?: (args: {
        itemId: string;
        canonicalItemId?: string;
        contentKind?: string;
    }) => void;
    handleItemPlayerError?: (args: {
        itemId: string;
        canonicalItemId?: string;
        contentKind?: string;
        error: unknown;
        timestamp?: number;
    }) => void;
    reportSectionError?: (args: {
        source: "item-player" | "section-runtime" | "toolkit" | "controller";
        error: unknown;
        itemId?: string;
        canonicalItemId?: string;
        contentKind?: string;
        timestamp?: number;
    }) => void;
    updateItemSession?: (itemId: string, sessionDetail: unknown) => {
        eventDetail?: unknown;
    } | null;
    subscribe?: (listener: (event: SectionControllerEvent) => void) => () => void;
    navigateToItem?: (index: number) => unknown;
}
/**
 * Initialize args used by the toolkit CE to resolve the coordinator-backed
 * section controller.
 */
interface EngineInitArgs {
    coordinator: ToolkitCoordinator;
    section: unknown;
    sectionId: string;
    assessmentId: string;
    view: string;
    attemptId?: string;
    createDefaultController: () => Promise<RuntimeController> | RuntimeController;
    onCompositionChanged?: (composition: unknown) => void;
}
/**
 * Engine-side `attachHost` args. The host element, framework-error bus,
 * and `sourceCe` together let the adapter dispatch DOM events and bus
 * fan-outs consistently with the kernel emit chain.
 */
export interface SectionRuntimeEngineHostArgs {
    host: EventTarget;
    sourceCe: string;
    frameworkErrorBus: FrameworkErrorReporter;
    coordinator?: SectionEngineAdapterOptions["coordinator"];
    instrumentationHook?: InstrumentationHook;
    now?: () => string;
}
export declare class SectionRuntimeEngine {
    private readonly registry;
    private readonly runtimeId;
    private adapter;
    private controller;
    private coordinator;
    private sectionId;
    private attemptId;
    private unsubscribeController;
    private activeInitToken;
    /**
     * Tracks which `(canonicalItemId, contentKind)` pairs have already
     * fired `handleContentLoaded` on this engine. Mirrored alongside
     * `RuntimeRegistry`'s registered set so a cohort handoff can
     * replay the persistent shells' loaded state into the new
     * controller — see `replayRegisteredShellsIntoController` and the
     * PIE-512 Phase B regression test.
     *
     * Cleared in lockstep with `handleContentUnregistered` and on
     * `dispose`. Not exposed publicly: the registry alone is the
     * external surface; the loaded set exists only to seed cohort B's
     * controller with the live state cohort A's shells produced.
     */
    private readonly loadedRenderableKeys;
    /**
     * Attach the host element + framework-error bus + sourceCe so the
     * adapter can dispatch DOM events and bus errors. Required before
     * `dispatchInput` / `subscribe` produce observable effects.
     *
     * Constructs the adapter on the first call. Subsequent calls keep
     * the adapter and update its host element / instrumentation hook
     * (used by layout-shell rollovers and instrumentation reconfig).
     */
    attachHost(args: SectionRuntimeEngineHostArgs): void;
    /**
     * Forward a host-constructed input to the FSM core via the adapter.
     * Returns the outputs the transition produced (subscribers and the
     * DOM/framework-error/instrumentation bridges have already
     * received them).
     *
     * No-op (returns `[]`) before `attachHost(...)` so callers that
     * dispatch optimistically during teardown do not throw.
     */
    dispatchInput(input: SectionEngineInput): readonly SectionEngineOutput[];
    /**
     * Subscribe to batched engine outputs (one batch per
     * `dispatchInput`). Returns an idempotent disposer. Pre-`attachHost`
     * subscriptions return a no-op disposer so callers can wire
     * subscriptions early without lifecycle-ordering hazards.
     */
    subscribe(listener: EngineOutputListener): () => void;
    /**
     * Read-only snapshot of the FSM state. Returns the initial idle
     * state before `attachHost` so callers can probe state without
     * special-casing the pre-attach phase.
     */
    getState(): Readonly<SectionEngineState>;
    /**
     * Resolve the effective runtime + tools snapshot for the given
     * two-tier inputs. This is a pure function over the resolver — it
     * does not depend on adapter state — so callers can use it both
     * pre- and post-`attachHost`. The kernel uses it to seed
     * `dispatchInput({ kind: "initialize", effectiveRuntime, ... })`.
     */
    getEffectiveRuntime<P>(args: RuntimeInputs, deps: {
        resolvePlayerRuntime: (resolverArgs: {
            effectiveRuntime: Record<string, unknown>;
            playerType: string;
            env: Record<string, unknown> | null;
        }) => P;
    }): EffectiveRuntime;
    /**
     * Update the adapter's instrumentation hook. No-op pre-attach.
     * Hosts that always want a hook should pass it via `attachHost`.
     */
    setInstrumentationHook(hook: InstrumentationHook | undefined): void;
    /**
     * Stable per-engine runtime id used to scope DOM-event details and
     * registry telemetry. Exposed so tests and instrumentation can pin
     * the value the bridges emit.
     */
    getRuntimeId(): string;
    initialize(args: EngineInitArgs): Promise<void>;
    /**
     * Re-feed the engine's `RuntimeRegistry` and loaded-set into the
     * resolved controller. Call site: `initialize(...)` — runs on
     * EVERY initialize, both cohort-flip-resolves-fresh-controller
     * and same-cohort-resolves-existing-controller cases. Phase C
     * dropped the `resolved !== previousController` gate; see the
     * comment at the call site for why.
     *
     * Two-pass order — register every shell in document order, then
     * issue `handleContentLoaded` for each shell whose load already
     * fired on this engine. The two-pass shape prevents
     * `evaluateSectionLoadingState` from flapping
     * `section-loading-complete` `false→true→false→…` while replay is
     * mid-walk: any subscriber wired before the engine's own
     * `controller.subscribe` (no such caller today, but cheap defense
     * for future wiring) sees one clean `false→true` transition.
     *
     * Idempotent on the controller side — Phase C makes
     * `SectionController.handleContentRegistered` and
     * `handleContentLoaded` early-return on duplicates so re-feeding
     * the same shells into a controller that already tracks them is
     * a true no-op (no spurious re-emits, no re-evaluation of
     * `section-loading-complete`). At the call site no listener is
     * attached during the replay window, so `emitChange` side effects
     * fire into a void on this pass anyway, but the controller-side
     * idempotence is what makes the replay safe to run on every
     * initialize regardless of whether the controller is fresh.
     */
    private replayRegisteredShellsIntoController;
    /**
     * Stable key for the engine's `loadedRenderableKeys` set. Mirrors
     * the `(canonicalItemId, contentKind)` shape `SectionController`
     * uses internally (see `getRenderableKey`); we only need
     * consistent add/check semantics on this side, not byte-identical
     * normalization with the controller.
     */
    private getLoadedKey;
    register(detail: RuntimeRegistrationDetail): boolean;
    unregister(element: HTMLElement): boolean;
    getCompositionModel(): unknown;
    getCanonicalItemId(itemId: string): string;
    handleContentRegistered(detail: RuntimeRegistrationDetail): void;
    handleContentUnregistered(detail: RuntimeRegistrationDetail): void;
    handleContentLoaded(args: {
        itemId: string;
        canonicalItemId?: string;
        contentKind?: string;
        detail?: unknown;
        timestamp?: number;
    }): void;
    handleItemPlayerError(args: {
        itemId: string;
        canonicalItemId?: string;
        contentKind?: string;
        error: unknown;
        timestamp?: number;
    }): void;
    reportSectionError(args: {
        source: "item-player" | "section-runtime" | "toolkit" | "controller";
        error: unknown;
        itemId?: string;
        canonicalItemId?: string;
        contentKind?: string;
        timestamp?: number;
    }): void;
    updateItemSession(itemId: string, session: unknown): unknown;
    navigateToItem(index: number): unknown;
    persist(): Promise<void>;
    hydrate(): Promise<void>;
    getRegistry(): RuntimeRegistry;
    dispose(): Promise<void>;
}
export {};
