/**
 * Tool Registry
 *
 * Central registry for all assessment tools. Manages tool metadata, visibility logic,
 * and button/instance creation. Supports dynamic registration and override by integrators.
 */
import type { ToolContext, ToolLevel } from "./tool-context.js";
import type { ToolComponentOverrides } from "../tools/tool-tag-map.js";
import type { ElementToolStateStoreApi, ToolCoordinatorApi, ToolkitCoordinatorApi, TtsServiceApi } from "./interfaces.js";
import type { ToolProviderApi } from "./tool-providers/ToolProviderApi.js";
import type { ToolProviderConfig as ToolRuntimeConfig } from "./tools-config-normalizer.js";
import type { ToolConfigDiagnostic } from "./tool-config-validation.js";
export type ToolModuleLoader = () => Promise<unknown>;
export interface ToolToolbarButtonDefinition {
    toolId: string;
    label: string;
    icon: string;
    ariaLabel: string;
    tooltip?: string;
    onClick: () => void;
    className?: string;
    disabled?: boolean;
    active?: boolean;
}
export interface ToolbarContext {
    scope: {
        level: ToolLevel;
        scopeId: string;
        assessmentId?: string;
        sectionId?: string;
        itemId?: string;
        canonicalItemId?: string;
        contentKind?: string;
    };
    itemId: string;
    catalogId: string;
    language: string;
    ui?: {
        size?: string;
    };
    getScopeElement?: () => HTMLElement | null;
    getGlobalElementId?: () => string | null;
    toolCoordinator: ToolCoordinatorApi | null;
    toolkitCoordinator: ToolkitCoordinatorApi | null;
    ttsService: TtsServiceApi | null;
    elementToolStateStore: ElementToolStateStoreApi | null;
    toggleTool: (toolId: string) => void;
    isToolVisible: (toolId: string) => boolean;
    subscribeVisibility: ((listener: () => void) => () => void) | null;
    componentOverrides?: ToolComponentOverrides;
    getResolvedToolContext?: (toolId: string) => ResolvedToolContext | null;
    getToolRenderParams?: (toolId: string) => Record<string, unknown> | null;
}
export interface ToolContextResolverContext {
    toolId: string;
    context: ToolContext;
    toolbarContext: ToolbarContext;
}
export interface ToolContextResolverResult {
    visible?: boolean;
    params?: Record<string, unknown>;
    reason?: string;
}
export type ToolContextResolver = (context: ToolContextResolverContext) => ToolContextResolverResult | null | undefined;
export type ToolContextResolverMap = Record<string, ToolContextResolver | null | undefined>;
export interface ResolvedToolContext {
    toolId: string;
    visible: boolean;
    params: Record<string, unknown>;
    reason?: string;
}
export interface ToolRenderElement {
    element: HTMLElement | null;
    mount: "before-buttons" | "after-buttons" | "controls-row";
    layoutHints?: {
        controlsRow?: {
            reserveSpace?: boolean;
            showWhenToolActive?: boolean;
        };
    };
    shell?: ToolWindowShellConfig;
}
export interface ToolWindowShellAction {
    id: string;
    label: string;
    ariaLabel?: string;
    iconSvg?: string;
    onClick: () => void;
}
/**
 * Alignment corner for the initial shell position.
 * The shell is offset by `initialMargin` (default 16 px) from the chosen corner.
 */
export type ToolWindowShellAlign = "center" | "top-left" | "top-right" | "bottom-left" | "bottom-right";
export interface ToolWindowShellConfig {
    title?: string;
    draggable?: boolean;
    resizable?: boolean;
    closeable?: boolean;
    initialWidth?: number;
    initialHeight?: number;
    minWidth?: number;
    minHeight?: number;
    maxWidth?: number;
    maxHeight?: number;
    /** Initial placement of the shell. Defaults to `'center'`. */
    initialAlign?: ToolWindowShellAlign;
    /** Distance (px) from the viewport edge when using a corner align. Defaults to 16. */
    initialMargin?: number;
    actions?: ToolWindowShellAction[];
}
export interface HostedToolContext {
    toolId: string;
    toolbarContext: ToolbarContext;
    shellConfig: ToolWindowShellConfig;
}
export interface HostedToolSize {
    width: number;
    height: number;
}
export interface ToolProviderDescriptor {
    getProviderId?: (config: ToolRuntimeConfig | undefined) => string;
    createProvider: (config: ToolRuntimeConfig | undefined) => ToolProviderApi;
    getInitConfig?: (config: ToolRuntimeConfig | undefined) => Record<string, unknown>;
    sanitizeConfig?: (config: ToolRuntimeConfig) => ToolRuntimeConfig;
    validateConfig?: (config: ToolRuntimeConfig) => ToolConfigDiagnostic[];
    getAuthFetcher?: (config: ToolRuntimeConfig | undefined) => (() => Promise<Record<string, unknown>>) | undefined;
    lazy?: boolean;
}
export interface ToolToolbarRenderResult {
    toolId: string;
    elements?: ToolRenderElement[];
    button?: ToolToolbarButtonDefinition | null;
    sync?: () => void;
    subscribeActive?: (callback: (active: boolean) => void) => () => void;
}
export type ToolActivation = "toolbar-toggle" | "selection-gateway";
export type ToolSingletonScope = "section";
/**
 * Tool registration interface
 */
export interface ToolRegistration {
    /** Unique tool identifier (e.g., 'calculator', 'textToSpeech') */
    toolId: string;
    /** Human-readable name */
    name: string;
    /** Description of what the tool does */
    description: string;
    /** Icon identifier or SVG string */
    icon: string | ((context: ToolContext) => string);
    /** Which levels this tool supports */
    supportedLevels: ToolLevel[];
    /**
     * Activation model for this tool.
     * - toolbar-toggle: rendered as a toolbar button (default)
     * - selection-gateway: rendered as a singleton selection-driven gateway
     */
    activation?: ToolActivation;
    /**
     * Optional singleton scope for activation models that mount exactly one instance.
     */
    singletonScope?: ToolSingletonScope;
    /**
     * PNP support IDs that enable this tool (optional)
     * Used by the tool policy engine to determine if a PNP support enables this tool.
     * Example: ['calculator', 'basic-calculator', 'scientific-calculator']
     */
    pnpSupportIds?: string[];
    /**
     * Optional provider registration metadata.
     * When present, ToolkitCoordinator can register provider(s) generically
     * without hardcoded tool-specific branches.
     */
    provider?: ToolProviderDescriptor;
    /**
     * Optional shell-host lifecycle hooks for hosted (floating) tools.
     */
    onHostedMount?: (element: HTMLElement, context: HostedToolContext) => void | Promise<void>;
    onHostedResize?: (size: HostedToolSize, element: HTMLElement, context: HostedToolContext) => void | Promise<void>;
    onHostedUnmount?: (element: HTMLElement, context: HostedToolContext) => void | Promise<void>;
    /**
     * Pass 2: Tool decides if it's relevant in this context
     * Called ONLY if orchestrator has already allowed the tool (Pass 1)
     *
     * @param context - Rich context about where tool is being evaluated
     * @returns true if tool should be visible, false to hide
     */
    isVisibleInContext(context: ToolContext): boolean;
    /** Required toolbar-first render contract. */
    renderToolbar(context: ToolContext, toolbarContext: ToolbarContext): ToolToolbarRenderResult | null;
}
/**
 * Tool Registry
 *
 * Manages tool registrations and provides query/lookup functionality
 */
export declare class ToolRegistry {
    private tools;
    private pnpIndex;
    private componentOverrides;
    private moduleLoaders;
    private loadedToolModules;
    private moduleLoadPromises;
    /**
     * Normalize a single tool alias to canonical toolId.
     */
    normalizeToolId(toolId: string): string;
    /**
     * Normalize a list of tool aliases to canonical toolIds.
     */
    normalizeToolIds(toolIds: string[]): string[];
    /**
     * Register a tool
     *
     * @param registration - Tool registration
     * @throws Error if toolId is already registered
     */
    register(registration: ToolRegistration): void;
    /**
     * Override an existing tool registration
     *
     * @param registration - New tool registration (must have existing toolId)
     */
    override(registration: ToolRegistration): void;
    /**
     * Unregister a tool
     *
     * @param toolId - Tool ID to remove
     */
    unregister(toolId: string): void;
    /**
     * Get a tool registration by ID
     *
     * @param toolId - Tool ID
     * @returns Tool registration or undefined
     */
    get(toolId: string): ToolRegistration | undefined;
    /**
     * Check if a tool is registered
     *
     * @param toolId - Tool ID
     * @returns true if registered
     */
    has(toolId: string): boolean;
    /**
     * Get all registered tool IDs
     *
     * @returns Array of tool IDs
     */
    getAllToolIds(): string[];
    /**
     * Get all tool registrations
     *
     * @returns Array of tool registrations
     */
    getAllTools(): ToolRegistration[];
    /**
     * Find tool IDs that support a given PNP support ID
     *
     * @param pnpSupportId - PNP support ID (e.g., 'calculator')
     * @returns Set of tool IDs that support this PNP ID
     */
    getToolsByPNPSupport(pnpSupportId: string): Set<string>;
    /**
     * Get tools that support a specific level
     *
     * @param level - Tool level (assessment, section, item, passage, element)
     * @returns Array of tool registrations that support this level
     */
    getToolsByLevel(level: ToolLevel): ToolRegistration[];
    /**
     * Resolve tool activation, defaulting to toolbar-toggle.
     */
    getToolActivation(toolId: string): ToolActivation;
    /**
     * Resolve singleton scope for a tool when present.
     */
    getToolSingletonScope(toolId: string): ToolSingletonScope | null;
    /**
     * Filter tool IDs by activation type.
     */
    filterToolIdsByActivation(toolIds: string[], activation: ToolActivation): string[];
    /**
     * Filter tools by visibility in a given context
     *
     * Pass 2 of the two-pass model: Given a list of allowed tool IDs (from Pass 1),
     * ask each tool if it's relevant in this context.
     *
     * @param allowedToolIds - Tool IDs that passed Pass 1 (orchestrator approval)
     * @param context - Context to evaluate
     * @returns Array of visible tool registrations
     */
    filterVisibleInContext(allowedToolIds: string[], context: ToolContext): ToolRegistration[];
    /**
     * Get tool metadata for building UIs
     * Useful for building PNP configuration interfaces
     *
     * @returns Array of tool metadata (id, name, description, pnpSupportIds)
     */
    getToolMetadata(): Array<{
        toolId: string;
        name: string;
        description: string;
        pnpSupportIds: string[];
        supportedLevels: ToolLevel[];
        activation: ToolActivation;
        singletonScope: ToolSingletonScope | null;
    }>;
    /**
     * Generate PNP support IDs from enabled tools
     * Useful for creating PNP profiles
     *
     * @param enabledToolIds - Tool IDs to enable
     * @returns Array of unique PNP support IDs
     */
    generatePNPSupportsFromTools(enabledToolIds: string[]): string[];
    /**
     * Clear all registrations (useful for testing)
     */
    clear(): void;
    /**
     * Configure global component overrides used by tool instance creation.
     */
    setComponentOverrides(overrides: ToolComponentOverrides): void;
    /**
     * Register lazy module loaders by toolId.
     * Toolbars call ensureToolModuleLoaded(toolId) before instance creation.
     */
    setToolModuleLoaders(loaders: Partial<Record<string, ToolModuleLoader>>): void;
    /**
     * Ensure tool module side-effects are loaded exactly once.
     * Safe to call repeatedly; concurrent callers share the same promise.
     */
    ensureToolModuleLoaded(toolId: string): Promise<void>;
    /**
     * Ensure a set of tool modules are loaded.
     */
    ensureToolModulesLoaded(toolIds: string[]): Promise<void>;
    /**
     * Whether a tool module has already been loaded.
     */
    isToolModuleLoaded(toolId: string): boolean;
    /**
     * Render a tool for toolbar use with component overrides attached.
     */
    renderForToolbar(toolId: string, context: ToolContext, toolbarContext: ToolbarContext): ToolToolbarRenderResult | null;
}
