import { SVGTemplateResult, nothing } from 'lit';
import { InstrumentState, Priority, FrameStyle, BorderRadiusPosition } from '../../navigation-instruments/types.js';
import { AdviceState, AdviceType } from '../../navigation-instruments/watch/advice.js';
/**
 * External Scale renderer (pure SVG building block).
 *
 * This module provides a side-aware, orientation-aware SVG “ruler/axis” renderer
 * that can be used standalone, as an overlay axis for charts, or composed inside
 * other components.
 *
 * Unlike Lit components, this file exports **pure functions** that return
 * `SVGTemplateResult` fragments. Consumers are responsible for creating the
 * outer `<svg>` element (including `viewBox`, sizing, and `preserveAspectRatio`).
 *
 * Note: this module also exports a few small DOM-oriented helpers used by the
 * web-component wrappers to read CSS variables (e.g. border radius) and observe
 * theme/size changes.
 *
 * ## What it renders
 * - **Bar container**: a rounded rectangle band (optional)
 * - **Bar fill**: value fill (0→value) or tinted range fill (fillMin→fillMax)
 * - **Tickmarks**: main + primary + secondary + tertiary tick lines (optional)
 * - **Labels**: numeric labels at primary tick interval (optional)
 * - **Advice overlays**: alert/advice/caution ranges with canonical dashed bounds
 * - **Setpoint marker**: a triangular marker that flips by side and scales when
 *   “at setpoint”
 *
 * ## Layout model
 * - `orientation`: `'vertical' | 'horizontal'` controls value→coordinate mapping
 * - `side`: where the scale attaches to the chart edge
 *   - vertical: `'left' | 'right'`
 *   - horizontal: `'top' | 'bottom'`
 * - The **chart edge is always at perpendicular coordinate `0`**.
 *   The scale expands outward into positive or negative perpendicular space
 *   depending on `side`.
 *
 * Use `computeExternalScaleLayout()` to compute the minimal viewBox thickness for
 * the selected bands (bar/ticks/labels).
 *
 * ## Theming & responsive sizing
 * This renderer uses CSS variables directly in SVG attributes.
 * It is designed to inherit theme and sizing variables from parent containers
 * (e.g. `.obc-component-size-*` wrappers) the same way web components do.
 *
 * Common variables involved:
 * - `--global-typography-ui-label-font-size`
 * - `--instrument-frame-*-color`, `--instrument-*-*-color`
 * - `--instrument-components-watchface-frame-regular-border-radius`
 *
 * **Browser note (SVG geometry + CSS variables):**
 * Some browsers (notably Chrome) do not reliably resolve `var(--...)` inside SVG
 * geometry/path calculations. When you need **selective corner rounding** (which
 * requires numeric path geometry), pass a numeric pixel value via
 * `ExternalScaleConfig.borderRadius`.
 *
 * The web-component wrappers (`obc-bar-vertical` / `obc-bar-horizontal`) compute
 * this numeric value from the CSS variable
 * `--instrument-components-watchface-frame-regular-border-radius` so component-size
 * wrappers (e.g. `.obc-component-size-*`) remain the source of truth.
 *
 * ## Usage examples
 *
 * ### Standalone usage
 * ```ts
 * import {html} from 'lit';
 * import {computeExternalScaleLayout, renderExternalScale} from './external-scale.js';
 *
 * const config = {
 *   orientation: 'vertical',
 *   side: 'right',
 *   length: 320,
 *   paddingStart: 32,
 *   paddingEnd: 32,
 *   minValue: 0,
 *   maxValue: 100,
 *   hasBar: true,
 *   hasScale: true,
 *   labels: true,
 *   scaleBackground: false,
 *   barThickness: 24,
 *   tickThickness: 24,
 *   labelThickness: 60,
 *   mainTickmarks: [],
 *   primaryTickmarkInterval: 20,
 *   secondaryTickmarkInterval: 10,
 *   tertiaryTickmarkInterval: 2,
 *   scaleType: ScaleType.regular,
 *   frameStyle: FrameStyle.regular,
 *   priority: Priority.enhanced,
 *   fillMode: FillMode.fill,
 *   fillMin: 0,
 *   fillMax: 40,
 *   value: 40,
 *   setpoint: 50,
 *   atSetpoint: false,
 *   autoAtSetpoint: true,
 *   autoAtSetpointDeadband: 1,
 *   setpointAtZeroDeadband: 0.5,
 *   state: InstrumentState.active,
 *   advicePosition: AdvicePosition.inner,
 *   advices: [{min: 60, max: 80, type: AdviceType.caution, hinted: true}],
 * };
 *
 * const layout = computeExternalScaleLayout(config);
 * const parts = renderExternalScale(config);
 *
 * // Wrap returned fragments in an SVG.
 * const tpl = html`<svg
 *   width="${layout.viewBoxThickness}px"
 *   height="${config.length}px"
 *   viewBox="${layout.viewBoxPerpStart} ${-config.length / 2} ${layout.viewBoxThickness} ${config.length}"
 *   preserveAspectRatio="none"
 * >
 *   ${parts.barContainer}
 *   ${parts.barFill}
 *   ${parts.scaleBackground}
 *   ${parts.tickmarks}
 *   ${parts.labels}
 *   ${parts.adviceOverlays}
 *   ${parts.setpoint}
 * </svg>`;
 * ```
 *
 * ### Web component wrappers
 * For common usage, prefer the thin wrappers:
 * - `obc-bar-vertical` (sets up vertical viewBox)
 * - `obc-bar-horizontal` (sets up horizontal viewBox)
 */
/** Main axis orientation for the external scale renderer. */
export declare enum ExternalScaleOrientation {
    vertical = "vertical",
    horizontal = "horizontal"
}
/** Which side of the chart area the scale is attached to. */
export declare enum ExternalScaleSide {
    left = "left",
    right = "right",
    top = "top",
    bottom = "bottom"
}
/** Tick density preset */
export declare enum ScaleType {
    regular = "regular",
    condensed = "condensed"
}
/** Fill visualization mode */
export declare enum FillMode {
    fill = "fill",
    tint = "tint"
}
/** Advice overlay position */
export declare enum AdvicePosition {
    center = "center",
    inner = "inner",
    outer = "outer"
}
/**
 * Bar container background style.
 * Controls the background color of the bar container independently of scaleBackground.
 */
export declare enum BarContainerStyle {
    /** Use lighter primary color (--instrument-frame-primary-color) */
    primary = "primary",
    /** Use darker secondary color (--instrument-frame-secondary-color) */
    secondary = "secondary"
}
/** CSS variable used by component-size wrappers to define frame corner rounding. */
export declare const EXTERNAL_SCALE_BORDER_RADIUS_CSS_VAR = "--instrument-components-watchface-frame-regular-border-radius";
/**
 * Parse a CSS length into pixels.
 *
 * Supports: `px`, `rem`, `em`, and unitless values (treated as px).
 * Returns `undefined` when parsing fails.
 */
export declare function parseCssLengthToPx(value: string, context?: {
    element?: Element;
    documentElement?: Element;
}): number | undefined;
/**
 * Read the external scale border radius CSS variable from an element and return
 * a numeric pixel value suitable for path-based selective corner rounding.
 *
 * Falls back to 4px for condensed and 8px for regular when CSS/DOM is unavailable.
 */
export declare function readExternalScaleBorderRadiusPx(host: Element, scaleType: ScaleType, cssVarName?: string): number;
/**
 * Start observing likely style-change sources (host + ancestors + documentElement)
 * and call `onChange` when class/style attributes change.
 *
 * Returns the MutationObserver instance, or `undefined` when MutationObserver/DOM
 * is unavailable.
 */
export declare function startExternalScaleBorderRadiusObserver(host: HTMLElement, onChange: () => void): MutationObserver | undefined;
/** Default border radius (px) used when `ExternalScaleConfig.borderRadius` is not provided. */
export declare function defaultExternalScaleBorderRadiusPx(scaleType: ScaleType): number;
/**
 * Compute a safe, numeric border radius (px) for geometry calculations.
 *
 * When `borderRadius` is undefined/invalid, falls back to a scaleType-based default.
 */
export declare function computeExternalScaleEffectiveBorderRadiusPx(config: Pick<ExternalScaleConfig, 'borderRadius' | 'scaleType'>): number;
/**
 * Compute the effective bar thickness.
 *
 * To keep rounded corners visually correct, the bar band must be at least
 * `2 * borderRadius` thick (otherwise the rounding geometry self-intersects).
 */
export declare function computeExternalScaleEffectiveBarThickness(config: Pick<ExternalScaleConfig, 'hasBar' | 'barThickness' | 'borderRadius' | 'scaleType'>): number;
/**
 * Compute the effective tick band thickness based on scale type.
 *
 * In condensed mode, ticks are shorter (max 10px for primary/main + 4px gap = 14px),
 * so the tick band doesn't need to be as thick as in regular mode (20px + 4px = 24px).
 *
 * This function ensures that:
 * - In regular mode: tickThickness is used as-is (minimum 24px for full-length ticks)
 * - In condensed mode: tickThickness is capped at 14px (10px tick + 4px gap)
 *
 * This allows wrappers to use a single default tickThickness (24px) while the layout
 * automatically adjusts for condensed mode.
 *
 * @param config - Configuration with tickThickness and scaleType
 * @returns Effective tick band thickness in pixels
 */
export declare function computeExternalScaleEffectiveTickThickness(config: Pick<ExternalScaleConfig, 'tickThickness' | 'scaleType'>): number;
export interface ExternalScaleAdvice {
    /** Range start value (in scale units). */
    min: number;
    /** Range end value (in scale units). */
    max: number;
    type: AdviceType;
    /** When true, renders in a "hinted" state unless the setpoint is inside the range. */
    hinted: boolean;
}
export interface ExternalScaleAdviceRaw {
    min: number;
    max: number;
    type: AdviceType;
    state: AdviceState;
}
export interface ExternalScaleConfig {
    /** Main axis orientation used for value-to-coordinate mapping. */
    orientation: ExternalScaleOrientation;
    /**
     * Which side of the chart area this scale lives on.
     * - vertical: 'left' | 'right'
     * - horizontal: 'top' | 'bottom'
     */
    side: ExternalScaleSide;
    /** Total length in pixels (vertical: height, horizontal: width), including padding. */
    length: number;
    /** Padding at start of main axis (top for vertical, left for horizontal). */
    paddingStart: number;
    /** Padding at end of main axis (bottom for vertical, right for horizontal). */
    paddingEnd: number;
    /** Minimum scale value. */
    minValue: number;
    /** Maximum scale value. */
    maxValue: number;
    /** Show scale tickmarks. */
    hasScale: boolean;
    /** Show labels at primary tickmark intervals. */
    labels?: boolean;
    /** Show bar. */
    hasBar: boolean;
    /** Show background behind the scale tickmarks. */
    scaleBackground: boolean;
    /** Bar band thickness in pixels (the container / fill area). */
    barThickness: number;
    /**
     * Bar container background style.
     * When undefined, defaults based on scaleBackground:
     * - scaleBackground=true: secondary (gray)
     * - scaleBackground=false: primary (lighter)
     * Set explicitly to override this default behavior.
     */
    barContainerStyle?: BarContainerStyle;
    /** Tickmark band thickness in pixels (space reserved for tick lines). */
    tickThickness: number;
    /** Label band thickness in pixels (space reserved for numbers). */
    labelThickness: number;
    /** Array of values for main tickmarks. Defaults to [minValue, 0, maxValue] if empty. */
    mainTickmarks?: number[];
    /**
     * Interval for primary tickmarks. When undefined, no primary tickmarks are shown.
     * When a positive number, primary tickmarks are shown at that interval.
     */
    primaryTickmarkInterval?: number;
    /**
     * Interval for secondary tickmarks. When undefined, no secondary tickmarks are shown.
     * When a positive number, secondary tickmarks are shown at that interval.
     */
    secondaryTickmarkInterval?: number;
    /**
     * Interval for tertiary tickmarks. When undefined, no tertiary tickmarks are shown.
     * When a positive number, tertiary tickmarks are shown at that interval.
     */
    tertiaryTickmarkInterval?: number;
    /**
     * Tick density preset.
     * - ScaleType.regular: longer ticks
     * - ScaleType.condensed: shorter ticks
     */
    scaleType: ScaleType;
    /**
     * Frame style preset.
     * - FrameStyle.regular: all ticks offset from bar edge by a gap
     * - FrameStyle.flat: main ticks touch the bar edge
     * - FrameStyle.framed: framed appearance
     * - FrameStyle.instrument: instrument-style appearance
     */
    frameStyle: FrameStyle;
    /**
     * Border radius position based on component layout.
     * Determines which corners receive rounded borders.
     */
    borderRadiusPosition?: BorderRadiusPosition;
    /**
     * Override border radius value (in pixels).
     * When undefined, uses default based on scaleType (4px for condensed, 8px for regular).
     * Set this to the computed CSS variable value to make path-based selective corner
     * rounding respond to theme changes.
     */
    borderRadius?: number;
    /**
     * Color priority mode.
     * - `Priority.enhanced`: Use enhanced (blue) color palette
     * - `Priority.regular`: Use regular (gray) color palette
     */
    priority: Priority;
    /**
     * When true, the setpoint color is derived from `priority` regardless of
     * instrument state (loading/off). This prevents the setpoint from being
     * rendered in disabled (tertiary) color when the instrument is loading or off.
     *
     * - `false` / `undefined`: default behavior — loading/off → disabled color
     * - `true`: color derived from `priority`, never disabled
     *
     * @default false
     */
    setpointOverride?: boolean;
    /**
     * Explicit disabled state override for setpoint marker.
     * When true, the setpoint uses tertiary/disabled colors.
     * When undefined, disabled state is auto-derived from `state` (loading/off = disabled).
     *
     * @default undefined (auto-derived from state)
     */
    setpointDisabled?: boolean;
    /**
     * Fill visualization mode.
     * - FillMode.fill: bar fill from fillMin to fillMax
     * - FillMode.tint: bar fill from fillMin to fillMax with marker at value position
     */
    fillMode: FillMode;
    fillMin?: number;
    fillMax?: number;
    /** Current value used for fill and/or marker rendering. */
    value?: number;
    /**
     * Setpoint value. When undefined, no setpoint marker is shown.
     * When a number, the setpoint marker is shown at that value.
     */
    setpoint?: number;
    /**
     * New setpoint value being adjusted (focus mode).
     * When defined, renders a second setpoint marker in 'focus' visual state.
     * The original `setpoint` marker is dimmed (0.5 opacity) while `newSetpoint` is active.
     * This enables the "adjustment preview" UX where users can see both the current
     * and proposed setpoint positions simultaneously.
     */
    newSetpoint?: number;
    /** Manual override used when autoAtSetpoint=false. */
    atSetpoint: boolean;
    /** When true, at-setpoint is derived from value/setpoint and deadband. */
    autoAtSetpoint: boolean;
    /** Deadband used for automatic at-setpoint detection. */
    autoAtSetpointDeadband: number;
    /** Deadband around 0 where the setpoint indicator snaps to exactly 0. */
    setpointAtZeroDeadband: number;
    state: InstrumentState;
    /** Where advice overlays are drawn relative to the bar/tick bands. */
    advicePosition: AdvicePosition;
    /** Array of advice ranges (min/max/type/hinted). */
    advices?: ExternalScaleAdvice[];
    /**
     * When true, freezes all internal calculations and scales the entire component
     * proportionally (like CSS transform:scale), except label font-size remains constant.
     * When false (default), dimensions react to component properties.
     * @default false
     */
    fixedAspectRatio?: boolean;
    /**
     * Reference size for proportional scaling when fixedAspectRatio is true.
     * At this size, the scale renders at native 1:1 (matches Figma design).
     * Above this size, the scale grows proportionally; below, it shrinks.
     * Applied to the main axis dimension (height for vertical, width for horizontal).
     * @default 384
     */
    scaleReferenceSize?: number;
    /**
     * When true, the component is used inside an instrument (e.g., gauge-trend).
     * In this mode, only label font size responds to .obc-component-size-* CSS classes.
     * Border radius uses the explicit `borderRadius` property value (or defaults to 8px regular / 4px condensed),
     * rather than reading from CSS variables.
     *
     * Wrappers should:
     * - Skip CSS variable observers when instrumentMode=true
     * - Use explicit borderRadius value or scaleType-based defaults
     *
     * @default false
     */
    instrumentMode?: boolean;
    /**
     * When true, displays a dot indicator at the current value position.
     * The dot is rendered in the scale band, touching its inner edge (towards the chart).
     * This provides an alternative to bar fill for highlighting the current value.
     *
     * The dot is:
     * - 12x12px filled circle with 2px stroke (16px total visual size)
     * - Fill: --instrument-regular-secondary-color (or enhanced variant when priority=enhanced)
     * - Stroke: --instrument-frame-primary-color
     *
     * @default false
     */
    highlightCurrentValue?: boolean;
    /**
     * User is physically interacting with the control (e.g. lever/slider touch).
     *
     * When true:
     * - `calculateAtSetpoint()` returns false (suppressed)
     * - Single setpoint marker renders in focus visual state
     *
     * @default false
     */
    touching?: boolean;
    /**
     * Enable CSS-animated confirm transition for setpoint markers.
     * When true, the original setpoint marker uses CSS `transition` for smooth movement
     * and opacity changes. The departing new-setpoint marker fades out.
     *
     * Duration is configurable via CSS: `--setpoint-animation-duration: 300ms`.
     * @default false
     */
    animateSetpoint?: boolean;
    /**
     * Value of the departing new-setpoint during confirm animation.
     * When defined, renders the new-setpoint marker at this position with `opacity: 0`
     * (CSS-transitioned from 1), keeping it in the DOM during its fade-out.
     *
     * Managed by SetpointMixin / SetpointBundle — cleared after animation completes.
     */
    departingNewSetpoint?: number;
}
export interface ExternalScaleLayout {
    /** Total thickness (vertical: width, horizontal: height) */
    thickness: number;
    /** Where the viewBox begins on the perpendicular axis (chart-edge is always 0) */
    viewBoxPerpStart: number;
    /** viewBox length (main axis) */
    viewBoxLength: number;
    /** viewBox thickness (perpendicular axis) */
    viewBoxThickness: number;
}
export type ExternalScaleLayoutConfig = Pick<ExternalScaleConfig, 'orientation' | 'side' | 'hasBar' | 'hasScale' | 'labels' | 'barThickness' | 'tickThickness' | 'labelThickness' | 'length' | 'scaleType'>;
export interface ExternalScaleViewBox {
    x: number;
    y: number;
    width: number;
    height: number;
}
/** Convenience helper for producing the `computeExternalScaleLayout()` input from a full config. */
export declare function toExternalScaleLayoutConfig(config: ExternalScaleConfig): ExternalScaleLayoutConfig;
/**
 * Compute the outer SVG viewBox for a scale given layout.
 * Wrappers can use this to avoid duplicating orientation-specific math.
 */
export declare function computeExternalScaleViewBox(config: Pick<ExternalScaleConfig, 'orientation' | 'length'>, layout: ExternalScaleLayout): ExternalScaleViewBox;
/**
 * Compute the effective `preserveAspectRatio="xMidYMid meet"` uniform scale factor.
 *
 * Returns 1 when inputs are invalid (e.g. 0-sized viewBox).
 */
export declare function computeMeetScale(viewBoxWidth: number, viewBoxHeight: number, containerWidth: number, containerHeight: number): number;
/**
 * Configuration for computing fixed aspect ratio scale factor.
 */
export interface FixedAspectRatioScaleConfig {
    /** Main axis orientation: 'vertical' or 'horizontal' */
    orientation: ExternalScaleOrientation;
    /** Actual main axis size of the container (height for vertical, width for horizontal) */
    containerMainAxisSize: number;
    /** Reference size at which the scale renders at 1:1 (default: 384) */
    scaleReferenceSize: number;
}
/**
 * Compute the scale factor for fixed aspect ratio mode.
 *
 * In fixed aspect ratio mode, the scale component determines its zoom level based on
 * comparing the container's main axis size against a reference size (typically 384px).
 * - If container is larger than reference: scale > 1 (zoom in)
 * - If container is smaller than reference: scale < 1 (zoom out)
 * - If container equals reference: scale = 1 (native size)
 *
 * This scale factor is applied to SVG rendering while keeping text labels at constant size
 * by using the CSS variable `--scale` to counter-scale font sizes.
 *
 * Works for all orientations and sides:
 * - Vertical scales (left/right): compare container height vs reference
 * - Horizontal scales (top/bottom): compare container width vs reference
 *
 * @param config Configuration with orientation, container size, and reference size
 * @returns Scale factor (> 0), defaults to 1 if container size is invalid
 */
export declare function computeFixedAspectRatioScale(config: FixedAspectRatioScaleConfig): number;
/**
 * Compute scaled dimensions for reporting when in fixed aspect ratio mode.
 *
 * When fixedAspectRatio is true, the reported thickness should be scaled
 * proportionally to match the visual output.
 *
 * @param baseThickness The unscaled thickness from layout computation
 * @param scale The current scale factor from computeFixedAspectRatioScale
 * @returns Scaled thickness value
 */
export declare function computeScaledThickness(baseThickness: number, scale: number): number;
/**
 * Compute a minimal viewBox layout for an external scale.
 *
 * The chart edge is always at perpendicular coordinate 0, and the scale expands
 * outward from that edge based on which bands are enabled (bar/ticks/labels).
 *
 * When scaleType is 'condensed', tick thickness is automatically reduced to match
 * the shorter tick lengths (14px max instead of 24px for regular).
 */
export declare function computeExternalScaleLayout(config: ExternalScaleLayoutConfig): ExternalScaleLayout;
/**
 * Helper for web components to compute dimensions for reporting to parent charts.
 *
 * This calculates the minimal configuration needed to determine the scale's thickness,
 * avoiding the need to pass full configs with many irrelevant properties.
 *
 * @param config - Minimal layout configuration
 * @returns Object with side and thickness for event dispatching
 */
export declare function computeScaleDimensionsForReport(config: ExternalScaleLayoutConfig): {
    side: ExternalScaleSide;
    thickness: number;
};
/**
 * Render the external scale as SVG fragments.
 *
 * This is a pure renderer: it does not touch DOM state and expects the caller
 * to place the returned fragments inside an `<svg>` with an appropriate viewBox.
 *
 * @param config - Scale configuration
 */
export declare function renderExternalScale(config: ExternalScaleConfig): {
    barContainer: SVGTemplateResult | typeof nothing;
    barFill: SVGTemplateResult | typeof nothing;
    scaleBackground: SVGTemplateResult | typeof nothing;
    tickmarks: SVGTemplateResult[];
    labels: SVGTemplateResult[];
    adviceOverlays: SVGTemplateResult[];
    currentValueDot: SVGTemplateResult | typeof nothing;
    setpoint: SVGTemplateResult | typeof nothing;
};
//# sourceMappingURL=external-scale.d.ts.map