import type { Wafer } from '../core/wafer.js';
import type { Die, PositionedDie } from '../core/dies.js';
import type { Reticle } from '../core/reticle.js';
import type { DieMetadata, WaferMetadata } from '../core/metadata.js';
import { type Affine } from '../core/transforms.js';
import type { TestDef, BinDef, MetadataFieldDef, ReticleConfig } from './buildWaferMap.js';
/** Resolve a toolbar activeTest cursor to the canonical test number for getDieTestValue. */
export declare function resolveTestNumber(activeTest: number, testDefs?: TestDef[]): {
    testNumber: number;
};
/** Find a TestDef by its testNumber. Returns undefined when testDefs is absent or no match. */
export declare function findTestDef(testDefs: TestDef[] | undefined, testNumber: number): TestDef | undefined;
/** Return sorted unique test numbers present across a set of dies (from testValues keys). */
export declare function getUniqueTestNumbers(dies: Die[]): number[];
export type PlotMode = 'value' | 'hardBin' | 'softBin' | 'stackedValues' | 'stackedBins' | 'stackedSoftBins' | 'metadata';
interface Point {
    x: number;
    y: number;
}
export interface ViewRect {
    x: number;
    y: number;
    width: number;
    height: number;
    fill: string | number;
    type: 'hardBin' | 'softBin' | 'value' | 'stacked' | 'metadata';
    stack?: number[];
    metadata?: DieMetadata;
    /**
     * Out-of-spec indicator for value-mode dies drawn with the value gradient.
     * The die keeps its gradient fill (so the distribution stays readable) and the
     * renderer draws a ▽ (`failLow`) / △ (`failHigh`) marker on top so the die is
     * never shown as plain in-spec. Set in both `'spec'` and `'data'` colorbar
     * ranges. Absent only under a pass/fail display (`passFailDisplay: 'spec'`),
     * where the solid categorical fill is itself the indication and no marker is needed.
     */
    specMark?: 'failLow' | 'failHigh';
}
export interface ViewText {
    x: number;
    y: number;
    text: string;
    fontSize: number;
    color: string;
    align: 'center';
    /** Marks fixed-size overlay labels (currently only the +X/+Y orientation
     *  indicators) so canvas-adapter excludes them from die-label uniform sizing.
     *  Absent = an ordinary die label; its `fontSize` here is a build-time
     *  (mm-space, zoom-unaware) default for non-canvas consumers of ViewText —
     *  canvas-adapter recomputes the actual on-screen size at draw time. */
    role?: 'indicator';
}
export interface ViewHoverPoint {
    x: number;
    y: number;
}
export interface ViewOverlay {
    kind: 'wafer-boundary' | 'reticle' | 'probe-path' | 'ring-boundary' | 'quadrant-boundary' | 'xy-indicator';
    points: Point[][];
    closed: boolean;
    lineColor: string;
    lineWidth: number;
    fill?: string;
}
export interface View {
    rectangles: ViewRect[];
    hoverPoints: ViewHoverPoint[];
    texts: ViewText[];
    overlays: ViewOverlay[];
    plotMode: PlotMode;
    colorScheme: string;
    metadata: WaferMetadata | null;
    dies: Die[];
    /** Actual [min, max] of the value data used for color normalization. */
    valueRange: [number, number];
    /** True when every observed value for the active test is a whole number. Drives integer-only colorbar ticks. */
    allIntegerValues?: boolean;
    /** Named test definitions — populated when `testDefs` is passed to `buildWaferMap`. */
    testDefs?: TestDef[];
    /** Which `values[]` index is being displayed (for `value` plot mode). Default 0. */
    activeTest: number;
    /** True when log₁₀ scale is both requested and valid (vMin > 0). */
    logScale: boolean;
    /**
     * True when log₁₀ scale was *requested* (option or per-test default), regardless of whether it
     * was applied. When `logScaleRequested && !logScale` the data range included ≤ 0 and the view
     * fell back to linear — the colorbar reports this as "linear — log n/a".
     */
    logScaleRequested: boolean;
    /** Aggregation method label for `stackedValues` hover tooltips (e.g. `'mean'`). */
    aggrMethod?: string;
    /** Total wafers in lot — for `stackedBins` hover percentage calculation. */
    lotSize?: number;
    /**
     * Total effective axis flip (data-pipeline flip XOR interactive flip).
     *
     * @deprecated for coordinate maths — this and {@link rotation} are a *lossy*
     * summary: a summed angle plus XOR'd flip flags cannot represent
     * rotate→mirror→rotate, because rotation and mirroring don't commute. They are
     * correct only while `wafer.orientation` is 0. Use {@link gridToScreen} (or its
     * inverse) for anything positional. Retained for display code that only needs a
     * rough orientation hint, and because it is read back as a data-flip hint below.
     */
    axisFlip: {
        x: boolean;
        y: boolean;
    };
    /**
     * The data-pipeline axis flip ALONE (from `xAxisDirection`/`yAxisDirection`/
     * `coordinateOrigin`), with no interactive flip mixed in. `renderWaferMap` feeds
     * this back into `buildView` as `dataAxisFlip` on every rebuild; reading
     * {@link axisFlip} for that purpose double-counts an active interactive flip.
     */
    dataAxisFlip: {
        x: boolean;
        y: boolean;
    };
    /** Total effective rotation in degrees (wafer orientation + interactive rotation). See {@link axisFlip} on why this is lossy. */
    rotation: number;
    /**
     * Die-grid geometry → screen. THE authoritative display transform: composed from
     * the real pipeline in order, so it stays correct for any combination of wafer
     * orientation, data-axis flip and interactive rotate/flip. Invert it
     * (`affineInvert`) to map a screen position back to a die-grid position — this is
     * what axis tick labels do.
     */
    gridToScreen: Affine<'grid', 'screen'>;
    /** True when reticle geometry is present — used to conditionally show the reticle toolbar button. */
    hasReticle: boolean;
    /** True when the scene was built from lot-aggregated data (lotStack). Controls toolbar stacked-mode visibility. */
    isLotStack: boolean;
    /**
     * The *effective* pass/fail display for value mode, resolved by the library
     * from the request and the data (never trust the caller's flag alone):
     * - `'spec'` — dies coloured by spec pass/fail against the active test's limits.
     * - `'test'` — dies coloured by the tester's recorded verdict
     *   (`getTestPassStatus`). Forced automatically when the active test is
     *   functional (`testType: 'F'`) — a functional test has no value to plot.
     * - `'off'`  — continuous value gradient (or a non-value plot mode).
     */
    passFailDisplay: 'off' | 'spec' | 'test';
    /** True when `passFailDisplay === 'spec'` — kept for back-compat with existing consumers. */
    colorBySpec: boolean;
    /** Whether the colorbar range is anchored to spec limits ('spec') or data extents ('data'). */
    colorbarRangeMode: 'spec' | 'data';
    /** Wafer centre in scene/display mm coordinates (the rotation pivot). */
    waferCenter: {
        x: number;
        y: number;
    };
    /** Wafer radius in mm. */
    waferRadius: number;
    /** Unit vector pointing toward the notch/flat in display space (post-transform). Null when no notch. */
    notchDir: {
        x: number;
        y: number;
    } | null;
    /** Bin → die count for the active bin mode (hardBin or softBin). Undefined in value modes. */
    binCounts?: Map<number, number>;
    /** Value → die count for the active metadata field, `'metadata'` mode only. */
    metadataCounts?: Map<string, number>;
    /**
     * Value → resolved fill colour for the active metadata field, `'metadata'` mode only. The
     * single source of truth for metadata colours — built from the same filtered die population
     * as `metadataCounts`, so legend swatches (built from this map) always match die fills (also
     * built from this map). Consumers must read this rather than recomputing colours from
     * `metadataCounts`'s keys, or the two can diverge in ranking whenever iteration order differs.
     */
    metadataColorMap?: Map<string, string> | null;
    /** Which `die.metadata` key is active in `'metadata'` mode. */
    activeMetadataKey?: string;
    /** Named metadata-field definitions — populated when `metadataFields` is passed to `buildWaferMap`. */
    metadataFields?: MetadataFieldDef[];
    /**
     * Per-category die counts for `value` + `passFailDisplay: 'spec'` — drives the spec legend. Counts only
     * dies with a value (no-data dies excluded). Undefined outside spec mode.
     */
    specCounts?: {
        pass: number;
        failHigh: number;
        failLow: number;
    };
    /**
     * Per-category die counts for `value` mode with `passFailDisplay: 'test'` — drives the
     * Pass/Fail legend. Counts only dies with a recorded verdict (no-data dies excluded).
     * Undefined outside test pass/fail display.
     */
    passFailCounts?: {
        pass: number;
        fail: number;
    };
    /** Bounding box of all die centres in scene coordinates (mm). */
    dieBounds: {
        minX: number;
        maxX: number;
        minY: number;
        maxY: number;
    } | null;
}
export interface ViewOptions {
    plotMode?: PlotMode;
    showDieLabels?: boolean;
    showReticle?: boolean;
    showProbePath?: boolean;
    ringCount?: number;
    showRingBoundaries?: boolean;
    showQuadrantBoundaries?: boolean;
    showXYIndicator?: boolean;
    dieGap?: number;
    /** Named colour scheme — any scheme registered via registerColorScheme(). Default: 'default'. */
    colorScheme?: string;
    highlightBin?: number;
    /** Dim every die except this metadata value, `'metadata'` mode's analogue of `highlightBin`. */
    highlightMetadataValue?: string;
    interactiveTransform?: {
        rotation?: number;
        flipX?: boolean;
        flipY?: boolean;
    };
    /**
     * Explicit value colour normalization range.
     *
     * - Tuple `[min, max]`: applied to whichever test is active. The caller is
     *   responsible for keeping it consistent with `activeTest`.
     * - Object `{ test, range }`: applied **only** when `test` matches the active
     *   test. On mismatch the range is ignored and the scene auto-scales — this
     *   makes it impossible to colour one test's data against another test's
     *   range. Prefer this form when the range was computed for a specific test.
     *
     * When omitted entirely, the range is auto-computed from the die values present.
     */
    valueRange?: [number, number] | {
        test: number;
        range: [number, number];
    };
    /**
     * Controls the default colorbar range when the active testDef has spec limits.
     * `'spec'` (default when limits present): colorbar spans [limitLow, limitHigh].
     * `'data'`: colorbar spans the actual data min/max regardless of limits.
     */
    colorbarRangeMode?: 'spec' | 'data';
    /**
     * Reticle rectangles to overlay on the map.
     * Generated by `generateReticleGrid` or the `reticle` option on `buildWaferMap`.
     */
    reticles?: Reticle[];
    /** Named test definitions — one per `values[]` entry. */
    testDefs?: TestDef[];
    /**
     * Which `values[]` index to display in `value` plot mode. Default `0`.
     * When `testDefs` is provided, the toolbar mode dropdown offers one item per test.
     */
    activeTest?: number;
    /**
     * Which `die.metadata` key to display in `'metadata'` plot mode. Must match
     * a `key` in `metadataFields` (passed to `buildWaferMap`, not here — see
     * the `binDefs` parameter of `buildView`) for the field to be colored/
     * legended; dies without that key set render as no-data.
     */
    activeMetadataKey?: string;
    /**
     * 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;
    /**
     * Format to use for unitless values outside the normal display range [0.1, 9999].
     * `'engineering'` (default): multiples-of-3 exponent notation (e.g. `12E-6`).
     * `'si'`: SI prefix with no unit suffix (e.g. `12 µ`).
     * Values with a unit always use SI prefix regardless of this setting.
     */
    fallbackFormat?: 'si' | 'engineering';
    /**
     * Aggregation method label shown in hover tooltips for `stackedValues` mode.
     * E.g. `'mean'`, `'median'`, `'stddev'`, `'min'`, `'max'`.
     */
    aggregationMethod?: string;
    /**
     * Total number of wafers in the lot — used to compute bin occurrence percentage
     * in `stackedBins` hover tooltips.
     */
    lotSize?: number;
    /**
     * Axis flip baked in by the data pipeline (for LL/LR/UL/UR origins or explicit
     * `xAxisDirection`/`yAxisDirection`). Combined with `interactiveTransform` flip
     * to produce the total effective axis flip for tick labels.
     */
    dataAxisFlip?: {
        x: boolean;
        y: boolean;
    };
    /** Set to true when the scene is built from lot-aggregated data (lotStack). */
    isLotStack?: boolean;
    /**
     * Requested pass/fail display for `value` mode. The library resolves the
     * *effective* display from this request and the data (see `View.passFailDisplay`):
     * - `'spec'` — colour dies by spec pass/fail against the active test's limits
     *   (solid green / blue fail-low / red fail-high). Degrades to `'off'` when the
     *   active test has no limits.
     * - `'test'` — colour dies by the tester's recorded pass/fail verdict
     *   (`die.testPass`, via `getTestPassStatus`; solid green pass / red fail).
     *   Degrades to `'off'` when no die has a recorded verdict for the active test.
     * - `'off'` (default) — continuous value gradient.
     * A functional active test (`testType: 'F'`) always renders as `'test'`
     * regardless of this option — it has no value to plot.
     */
    passFailDisplay?: 'off' | 'spec' | 'test';
    /**
     * When true (default), partial (edge) dies — positions that only partially
     * overlap the wafer circle — are rendered in a muted grey.
     * Set to false to hide them entirely, matching real prober behaviour where
     * edge positions are never tested.
     */
    showPartialDies?: boolean;
}
interface ColorFns {
    forValue: (t: number) => string;
    forBin: (bin: number) => string;
}
/** A die's spec classification for `value` mode against the active test's limits. */
export type SpecCategory = 'pass' | 'failHigh' | 'failLow';
/**
 * Classify a value against the active test's spec limits, using the SAME rules as the value-mode
 * die colouring in `pushDieRectangles`. Returns null when there is no value. Shared by the colour
 * branch and the spec-count tally so the two never diverge.
 *
 * Out-of-spec *classification* depends ONLY on whether limits are defined — never on
 * `colorbarRangeMode`. An out-of-spec die is always flagged when limits exist, regardless of
 * how the colorbar is scaled. The *form* of the indication, decided in `pushDieRectangles`,
 * depends only on the effective `passFailDisplay`: under `'spec'` (pass/fail mode) the die gets a solid
 * green/blue/red categorical fill; in normal value/gradient mode it keeps the value gradient
 * fill (like every other die, so the distribution stays readable and out-of-spec colours don't
 * collide with the scheme) and is flagged with a ▽/△ marker (`ViewRect.specMark`). Either way
 * the die is never drawn as plain in-spec — the silent correctness bug this guards against.
 */
export declare function classifySpec(value: number | undefined, activeTestDef: {
    limitLow?: number;
    limitHigh?: number;
} | undefined): SpecCategory | null;
/** Options for {@link buildHoverText}. All fields are optional. */
export interface HoverTextOptions {
    testDefs?: TestDef[];
    hbinDefs?: BinDef[];
    sbinDefs?: BinDef[];
    fallbackFormat?: 'si' | 'engineering';
    /** Lot-stack aggregation method name — shown so the reader knows what the scalar means. */
    aggrMethod?: string;
    /** Number of wafers in the stack, used to annotate a count with its share of the lot. */
    lotSize?: number;
    waferMeta?: WaferMetadata | null;
    /** Active test number (value mode only) — leads the tooltip and gets an out-of-spec note. */
    activeTest?: number;
    /** Reticle geometry, when configured — appended as a "Reticle (col, row)" line below Die (x, y). */
    reticleConfig?: ReticleConfig;
}
export declare function buildHoverText(die: Die, plotMode: PlotMode, opts?: HoverTextOptions): string;
/**
 * The on-canvas map title split into two parts for placement around the colorbar/legend:
 * - `primary`   — the most important identifier, drawn ABOVE the colorbar/legend.
 * - `secondary` — supporting context (stack/wafer-count), drawn BELOW it. Empty when not needed.
 */
export interface MapTitleParts {
    primary: string;
    secondary: string;
}
/**
 * Build the on-canvas map title for any plot mode, derived from the View (+ optional bin defs so a
 * single-bin stacked card can name its bin). Returns a primary/secondary split so the renderer can
 * place the key identifier above the scale and the supporting context below it — keeping each line
 * short and never obscured.
 *
 * Primary / secondary per mode:
 * - value            → "{name} ({unit})"            / —
 * - stackedValues    → "{name} ({unit}) · {method}" / "stacked ({n} wafers)"
 * - hardBin/softBin  → "Hard Bin" / "Soft Bin"      / —
 * - stackedBins      → "Hard Bin {bin}" (or "Hard Bin") / "stacked ({n} wafers)"
 * - stackedSoftBins  → "Soft Bin {bin}" (or "Soft Bin") / "stacked ({n} wafers)"
 *
 * @param fallbackFormat unitless value formatting — matches the colorbar tick formatting.
 * @param binDefs the active bin defs (hbinDefs for hard modes, sbinDefs for soft) — used to name
 *   the bin on single-bin stacked cards.
 */
export declare function buildMapTitle(view: View, fallbackFormat?: 'si' | 'engineering', binDefs?: BinDef[]): MapTitleParts;
export declare function generateTextOverlay(dies: PositionedDie[], txCoords: Float64Array | null, options: {
    plotMode: PlotMode;
    colorFns: ColorFns;
    normalize: (v: number) => number;
    activeTest: number;
    valueRange: [number, number];
    testDefs?: TestDef[];
    fallbackFormat?: 'si' | 'engineering';
    /** Effective pass/fail display (see View.passFailDisplay). 'test' renders P/F verdict labels. */
    passFailDisplay?: 'off' | 'spec' | 'test';
    /** Active `die.metadata` key + its resolved value→color map, `'metadata'` mode only. */
    activeMetadataKey?: string;
    metadataColorMap?: Map<string, string> | null;
}): ViewText[];
/**
 * Build a renderer-agnostic scene from a wafer, dies, and display options.
 *
 * ```ts
 * buildView(wafer, dies, { plotMode: 'hardBin', reticles })
 * ```
 */
export declare function buildView(wafer: Wafer, dies: PositionedDie[], options?: ViewOptions, binDefs?: {
    hbinDefs?: BinDef[];
    sbinDefs?: BinDef[];
    metadataFields?: MetadataFieldDef[];
}): View;
/**
 * Return a stable string key for a die — guaranteed format `"x,y"`.
 *
 * Re-exported from `core/dies.ts`, where the canonical implementation lives so
 * that `stats/` and `canvas-adapter/` can share it without depending on
 * `renderer/`. Kept exported here to preserve the public `@wafertools/wafermap/renderer`
 * entry point.
 */
export { getDieKey } from '../core/dies.js';
//# sourceMappingURL=buildView.d.ts.map