import type { PlotMode } from '../renderer/buildView.js';
import type { Die } from '../core/dies.js';
import { type ToCanvasOptions } from './toCanvas.js';
import type { WaferMapResult } from '../renderer/buildWaferMap.js';
import type { StatsSummary } from '../stats/types.js';
import { type SaveImageHandler, type SaveTextHandler, type UserGuideExtension } from './toolbar.js';
import type { SummaryPanelOptions } from './summaryPanel.js';
import { type WarningsOptions } from './warnings.js';
import { type InsightsOptions } from './insightsTab.js';
/**
 * Stable display preferences — worth persisting to localStorage or a user profile.
 * These describe how the user wants to view wafer maps in general.
 */
export interface WaferPreferences {
    colorScheme?: string;
    /** Interactive rotation in degrees (0 | 90 | 180 | 270). */
    rotation?: 0 | 90 | 180 | 270;
    flipX?: boolean;
    flipY?: boolean;
    showDieLabels?: boolean;
    showRingBoundaries?: boolean;
    showQuadrantBoundaries?: boolean;
    showReticle?: boolean;
    showXYIndicator?: boolean;
    ringCount?: number;
    /** Legend position for bin modes. Default 'default'. */
    legendPosition?: 'default' | 'compact' | 'bottom' | 'top' | 'left' | 'floating';
    /**
     * When true, apply log₁₀ scale to value normalization and the colorbar.
     * Overrides the per-test TestDef.logScale default.
     * Falls back to linear when vMin ≤ 0.
     */
    logScale?: boolean;
    /**
     * Controls the default colorbar range when the active testDef has spec limits.
     * `'spec'` (default): colorbar spans [limitLow, limitHigh]; out-of-spec dies show fail colors.
     * `'data'`: colorbar spans actual data min/max; out-of-spec coloring still applies.
     */
    colorbarRangeMode?: 'spec' | 'data';
    /**
     * When true (default), partial (edge) dies are rendered in muted grey.
     * Set to false to hide them entirely, matching real prober behaviour where
     * positions outside the wafer circle are never tested.
     */
    showPartialDies?: boolean;
}
/**
 * Transient display state — describes the current view session, not worth persisting.
 * Changes frequently as the user navigates tests and modes.
 */
export interface WaferDisplayState {
    plotMode?: PlotMode;
    /**
     * Requested pass/fail display for `value` mode — `'spec'` (spec-limit judgement),
     * `'test'` (the tester's recorded verdict from `die.testPass`), or `'off'` (gradient).
     * The library resolves the effective display from the data; a functional active
     * test always renders as `'test'`. Toggled by the Overlays toolbar menu.
     */
    passFailDisplay?: 'off' | 'spec' | 'test';
    /**
     * Which test number to display in `value` plot mode. Default `0`.
     * Controlled by the mode dropdown when the result has testDefs.
     */
    activeTest?: number;
    /**
     * Which `die.metadata` key to display in `'metadata'` plot mode. Must match
     * a `key` in the result's `metadataFields`. Controlled by the mode dropdown
     * when the result has `metadataFields`.
     */
    activeMetadataKey?: string;
    highlightBin?: number;
    /** Dim every die except this metadata value in `'metadata'` mode — the analogue of `highlightBin`. */
    highlightMetadataValue?: string;
    /**
     * Explicit value colour normalization range.
     *
     * - Tuple `[min, max]`: applied to whichever test is active (caller owns the
     *   coupling with `activeTest`).
     * - Object `{ test, range }`: applied only when `test` matches the active
     *   test; ignored (auto-scale) on mismatch, so one test's data can never be
     *   coloured against another test's range. Prefer this when the range was
     *   computed for a specific test.
     *
     * When omitted, the range is auto-computed from the die values present.
     */
    valueRange?: [number, number] | {
        test: number;
        range: [number, number];
    };
    /**
     * Aggregation method for `stackedValues` mode.
     * Drives both the per-die aggregation and the hover tooltip label.
     * Accepted values: `'mean'` | `'median'` | `'stddev'` | `'min'` | `'max'` | `'count'`.
     * Defaults to `'mean'` when not set.
     */
    aggregationMethod?: string;
    /**
     * Total number of wafers in the lot — used to compute bin occurrence percentage
     * in `stackedBins` hover tooltips.
     */
    lotSize?: number;
}
/**
 * All scene-level options that the toolbar can control.
 * Combines stable {@link WaferPreferences} with transient {@link WaferDisplayState}.
 * The flat shape is unchanged — callers set any field directly.
 * Use the `category` hint in {@link RenderOptions.onViewOptionsChange} to decide
 * whether a change is worth persisting.
 */
export type WaferViewOptions = WaferPreferences & WaferDisplayState;
export interface RenderOptions extends Omit<ToCanvasOptions, 'viewport' | 'hbinDefs' | 'sbinDefs'> {
    /** Initial scene display options. All are overridable via the toolbar. */
    viewOptions?: WaferViewOptions;
    /** Called when the user hovers over a die. Null when leaving a die. */
    onHover?: (die: Die | null, event: MouseEvent) => void;
    /** Called when the user clicks a die. */
    onClick?: (die: Die, event: MouseEvent) => void;
    /** Called when the user completes a box-select. */
    onSelect?: (dies: Die[]) => void;
    /**
     * Called whenever the toolbar changes a scene option.
     * `changed` lists the keys that changed.
     * `category` is `'preference'` when all changed keys are {@link WaferPreferences},
     * `'state'` when all are {@link WaferDisplayState}, or `'mixed'` when both.
     * Use `category !== 'state'` to decide whether to persist the new options.
     */
    onViewOptionsChange?: (opts: WaferViewOptions, changed: (keyof WaferViewOptions)[], category: 'preference' | 'state' | 'mixed') => void;
    /** Show built-in floating tooltip on hover. Default true. */
    showTooltip?: boolean;
    /** Show the built-in toolbar. Default true. */
    showToolbar?: boolean;
    /**
     * Show a small always-visible metadata badge (lot, wafer ID, product, test
     * program, temperature, etc.) overlaid bottom-left on the canvas. Default
     * true. Independent of `showToolbar` and the Insights tab — this exists so
     * basic wafer/lot identity is never hidden behind a mode or toggle, without
     * costing any layout space (it's an overlay, not a layout element). Renders
     * nothing when the result has no metadata at all. Collapsed by default to a
     * single identifying line; click/Enter/Space expands in place to the full
     * field set.
     */
    showMetadataBadge?: boolean;
    /** Optional precomputed wafer-level stats summary. Enables the summary panel toggle button in the toolbar. */
    statsSummary?: StatsSummary;
    /**
     * Bin numbers treated as pass for yield calculation in the summary panel.
     * Defaults to `[1]`. Must match the `passBins` passed to `analyzeWaferMap` / `buildWaferMap`
     * to ensure the summary panel yield label is consistent with the rest of the display.
     */
    passBins?: number[];
    /**
     * 'full' (default) shows all toolbar controls.
     * 'view-only' shows only zoom, reset, box-select, and download — used by gallery cards.
     */
    toolbarControls?: 'full' | 'view-only';
    /**
     * Show the plot mode selector in the toolbar. Default true.
     * Set to false when the host application manages mode switching itself.
     */
    showPlotModeSelector?: boolean;
    /** Minimum zoom relative to fit. Default 0.4. */
    minZoom?: number;
    /** Maximum zoom relative to fit. Default 20. */
    maxZoom?: number;
    /** Filename for the PNG download (without extension). Default `'wafermap'`. */
    downloadFilename?: string;
    /**
     * Host hook for persisting the rendered PNG. When provided, the toolbar's save
     * action calls `onSaveImage(blob, suggestedName)` instead of triggering a
     * browser `<a download>` — letting embedded hosts (Tauri, Electron, WebView2)
     * route the image through a native save dialog. `suggestedName` includes the
     * `.png` extension and is derived from `downloadFilename`. When omitted, the
     * default browser download behaviour is unchanged.
     */
    onSaveImage?: SaveImageHandler;
    /**
     * Host hook for saving the Summary/Insights test-values table's "Export CSV"
     * button. Mirrors `onSaveImage` — when provided, called with
     * `(text, suggestedName, mimeType)` instead of triggering a browser
     * `<a download>` (a silent no-op in Tauri/Electron/WebView2). When omitted,
     * the default browser download behaviour is unchanged.
     */
    onSaveText?: SaveTextHandler;
    /**
     * Options for the always-available Summary panel — a docked panel
     * (metadata, yield, bin breakdown, ring/quadrant yield, test values, and
     * findings with severity/kind/region filters, click-to-highlight on the
     * map) toggled via the toolbar's "Summary" button whenever `statsSummary`
     * is supplied. Independent of `insights` below: this always shows/hides
     * its own toolbar button regardless of whether Insights is open, since
     * Insights has no map for a finding to highlight against.
     */
    summaryPanel?: SummaryPanelOptions;
    /**
     * Custom tooltip renderer. When provided, replaces the built-in tooltip content.
     * Return a string (set as innerHTML), an HTMLElement (appended directly), or null to suppress the tooltip.
     * The built-in tooltip wrapper (positioning, show/hide behaviour) is preserved.
     */
    renderTooltip?: (die: Die) => string | HTMLElement | null;
    /**
     * Show a help button in the toolbar that opens the built-in end-user guide in a modal.
     * Default false. Enable in applications that want to surface the guide without linking externally.
     */
    showHelpButton?: boolean;
    /**
     * Host-supplied content inserted into the built-in end-user guide window
     * (see `showHelpButton`) — e.g. a host app's own documentation, so the user
     * has one help button instead of two. See `UserGuideExtension`.
     */
    userGuideExtension?: UserGuideExtension;
    /** Override the expand action for both the expand button and the E key. Used by the gallery to route through its own modal logic. */
    onExpand?: () => void;
    /**
     * Show the toolbar expand button and enable the E-key shortcut. Default true.
     * Set false when the host already renders the map inside its own expanded/modal
     * context, where wmap's built-in expand modal would be redundant.
     */
    showExpandButton?: boolean;
    /**
     * Intrinsic height for the map. `renderWaferMap` fills its container, which
     * therefore must have a resolved height — in a plain document a bare `<div>`
     * has none and the map collapses to zero. Set this and the library sizes its
     * own wrapper instead, so the map renders with no container CSS required.
     * Accepts a number (px) or any CSS length (e.g. `'600px'`, `'70vh'`).
     * Omit it when the container already has a height (flex/grid child, absolute
     * inset, or an explicit CSS height). Width always comes from the container.
     */
    height?: number | string;
    /**
     * Cap the map's rendered width and height at this many CSS pixels. When
     * the container is larger, the map sits top-left aligned within it rather
     * than stretching to fill it. Number only (a fixed pixel ceiling, not a
     * responsive length like `height`). Omit for no cap (fills the container,
     * current behaviour). The expand button/E-key still opens the map at full
     * size, unaffected by this cap.
     */
    maxSize?: number;
    /**
     * Base `z-index` for wmap's transient overlays — toolbar menus, the die
     * tooltip, the expand modal, and the user-guide modal. wmap layers its own
     * overlays from this value upward (tooltip and the modal box sit one or two
     * above it). Set this when embedding a map inside your own modal/overlay so
     * wmap's menus and tooltips appear above it.
     *
     * Omit it and wmap defaults overlays to a high value (above typical app modal
     * layers), so they appear on top with no configuration. The value is applied
     * for the lifetime of this render and restored on `destroy()`.
     */
    zIndex?: number;
    /**
     * Show an "Insights" tab in the toolbar (see `InsightsOptions`). Selecting
     * it replaces the canvas with wmap's own chart suite, computed over this
     * one wafer's dies (the same suite `renderWaferGallery`'s own `insights`
     * shows for a whole lot, minus grouping — a single wafer has nothing to
     * group by).
     */
    insights?: InsightsOptions;
    /**
     * Built-in surfacing of the library's own data warnings (see `WarningsOptions`).
     *
     * Defaults to showing them: the library raises geometry advisories that mean
     * dies may be drawn in the wrong place, and analysis advisories that mean a
     * feature silently produced nothing. It has the information, so telling the
     * user is its responsibility rather than the caller's.
     *
     * Hosts with their own notification system should pass
     * `{ display: false, onWarning }` — the library still collects, de-duplicates
     * and severity-orders, and the host owns only presentation.
     */
    warnings?: WarningsOptions;
}
export interface WaferMapController {
    /** Update the die data (e.g. after a data reload) — rebuilds scene, preserves zoom/pan. */
    setDies(dies: Die[]): void;
    /** Replace the wafer map result entirely — updates both wafer geometry and die data, preserves zoom/pan. */
    setResult(result: WaferMapResult): void;
    /** Merge scene option overrides — rebuilds scene, preserves zoom/pan. */
    setOptions(opts: Partial<WaferViewOptions>): void;
    /** Return current scene options snapshot. */
    getOptions(): WaferViewOptions;
    /** Programmatically set the selected dies (renders highlight overlay). */
    setSelection(dies: Die[]): void;
    /** Clear the current selection. */
    clearSelection(): void;
    /** Reset zoom and pan to fitted view. */
    resetZoom(): void;
    /** Update the fallback format for unitless values and re-render. */
    setFallbackFormat(format: 'si' | 'engineering'): void;
    /** Replace the current stats summary used by the built-in Summary panel. */
    setStatsSummary(summary: StatsSummary | undefined): void;
    /** Show or hide the Summary toolbar button without affecting the panel's content. */
    setSummaryVisible(visible: boolean): void;
    /** Show or hide the scene-control toolbar buttons (mode, orientation, etc). */
    setViewControlsVisible(visible: boolean): void;
    /** Show or hide the expand toolbar button. */
    setExpandVisible(visible: boolean): void;
    /** Show or hide the help toolbar button. */
    setHelpButtonVisible(visible: boolean): void;
    /** Show or hide the metadata badge without affecting its content. */
    setMetadataBadgeVisible(visible: boolean): void;
    /**
     * Opens the built-in end-user guide window — the same action the help
     * toolbar button performs, but callable directly. Works regardless of
     * `showHelpButton`/`setHelpButtonVisible`'s current value, so a host that
     * hides wmap's own help button (e.g. to fold it into its own combined help
     * menu) can still trigger the guide without a DOM query against wmap's
     * internal button markup.
     */
    openUserGuide(): void;
    /** Close the auto-mounted Summary panel if it is open. No-op if no panel exists. */
    closeSummaryPanel(): void;
    /** Programmatically open/close the Insights tab. No-op if `insights.enabled` was not set. */
    setInsightsOpen(open: boolean): void;
    /** Move the floating tooltip into a different parent (e.g. a maximized modal box). */
    setTooltipParent(parent: HTMLElement): void;
    /**
     * Returns the current legend entries in `hardBin`/`softBin`/`metadata` modes, `null` in other
     * modes. Each entry includes the bin number (or metadata value string), display name, and color.
     */
    getActiveLegend(): Array<{
        bin: number | string;
        name: string;
        color: string;
    }> | null;
    /** Remove all event listeners and DOM elements. */
    destroy(): void;
}
export declare function classifyChanged(keys: (keyof WaferViewOptions)[]): 'preference' | 'state' | 'mixed';
/**
 * What `renderWaferMap` actually needs: a wafer and its dies, plus anything
 * else `buildWaferMap` would have produced *if* the caller went through it.
 *
 * A `WaferMapResult` satisfies this, so nothing changes for the ordinary
 * `buildWaferMap` → `renderWaferMap` path. The reason it isn't simply
 * `WaferMapResult` is `renderWaferGallery`: it renders every card through this
 * same function, but a card is a `WaferMapDisplayItem` — a hand-built or
 * gallery-synthesised shape carrying no `dataCoverage`, `viewport`,
 * `legendBox`, `binLegendRows` or `reticleConfig`. Those cards used to arrive
 * as `item as WaferMapResult`, which told the type checker the fields were
 * there when at runtime they were simply absent; reading one unguarded threw,
 * and each such read had to be found the hard way. Declaring them optional
 * hands that job back to the compiler.
 */
export type RenderableWaferMap = Pick<WaferMapResult, 'wafer' | 'dies'> & Partial<Omit<WaferMapResult, 'wafer' | 'dies'>>;
export declare function renderWaferMap(container: HTMLElement, result: RenderableWaferMap, options?: RenderOptions): WaferMapController;
//# sourceMappingURL=renderWaferMap.d.ts.map