import { SVGTemplateResult } from 'lit';
import { InstrumentState, Priority } from '../navigation-instruments/types.js';
/**
 * Pure visual states for setpoint rendering.
 *
 * These represent DESIGN variations only — no instrument logic here.
 * Parent instruments are responsible for mapping their state to these values.
 */
export declare enum SetpointVisualState {
    /**
     * Input ≠ Output (value has not reached setpoint)
     * - Full size (100%)
     * - Primary color
     */
    notEqual = "notEqual",
    /**
     * Input = Output (value equals setpoint, within deadband)
     * - Reduced size (80%)
     * - Primary color (no color change)
     */
    equal = "equal",
    /**
     * Input = Output = 0 (both value and setpoint are at zero)
     * - Reduced size (80%)
     * - Primary color
     * - Additional 8px outward offset from the scale
     */
    equalZero = "equalZero",
    /**
     * Focus state (user is actively adjusting/touching)
     * - Full size (100%)
     * - Filled shape with 2px colored border + 1px silhouette outside
     * - Regular: fill tertiary, border secondary
     * - Enhanced: fill base-blue-100, border neutral-enhanced
     * - Silhouette: --border-silhouette-color (both modes)
     */
    focus = "focus"
}
/**
 * Color palette mode — determines which color palette to use for rendering.
 *
 * This is an **internal** rendering enum. Parent instruments do not set this
 * directly; instead they set `setpointOverride: boolean` on the public API.
 * The derivation functions (`deriveRadialSetpointConfig`, `deriveSetpointColorMode`)
 * map `Priority` → `SetpointColorMode` internally.
 *
 * Note: Disabled state is handled via a separate `disabled` boolean flag,
 * not as part of this enum. This allows combining any color mode with
 * the disabled state.
 */
export declare enum SetpointColorMode {
    /** Use enhanced colors (typically for Priority.enhanced instruments) */
    enhanced = "enhanced",
    /** Use regular colors (typically for Priority.regular instruments) */
    regular = "regular"
}
/**
 * SVG path for filled (solid) setpoint triangle with all corners rounded (2px radius).
 *
 * Path is designed for a 26×21 bounding box with:
 * - Base at top (y ≈ 0.5)
 * - Tip at bottom (y ≈ 21), rounded
 * - Center at x = 13
 *
 * All three corners have ~2px rounding for a softer appearance.
 * Equal states use 80% scaling of this path.
 */
export declare const SETPOINT_PATH_FILLED = "M22.5918 0.5C25.014 0.50013 26.3186 3.34437 24.917 5.29199L15.0244 19.0371C14.0268 20.423 11.9635 20.423 10.9658 19.0371L1.07326 5.29199C-0.328328 3.34437 0.97623 0.500124 3.39845 0.5L22.5918 0.5Z";
/** Marker width in pixels */
export declare const SETPOINT_WIDTH = 26;
/** Marker height in pixels (tip to base) */
export declare const SETPOINT_HEIGHT = 21;
/** X-coordinate of the marker tip (center of the triangle base) */
export declare const SETPOINT_TIP_X = 13;
/** Y-coordinate of the marker tip */
export declare const SETPOINT_TIP_Y = 21;
/** Scale factor when marker is in "at setpoint" state (equal, equalZero) */
export declare const SETPOINT_AT_SCALE = 0.8;
/** Outward offset (px) for notEqual and focus states */
export declare const SETPOINT_NOT_EQUAL_OFFSET = 4;
/** Outward offset (px) for equalZero state */
export declare const SETPOINT_ZERO_OFFSET = 8;
/**
 * Default duration (ms) for the setpoint confirm animation.
 *
 * When `animateSetpoint=true` and a confirm transition occurs
 * (newSetpoint → undefined, setpoint → newValue):
 * - The original setpoint marker slides to the new position over this duration
 * - The original setpoint marker regains full opacity (0.75 → 1.0)
 * - The departing new-setpoint marker fades out (1 → 0 opacity)
 *
 * Consumers can override the duration via the CSS custom property
 * `--setpoint-animation-duration`.
 */
export declare const SETPOINT_ANIMATION_DURATION_MS = 300;
/**
 * CSS custom property name for the setpoint animation duration.
 * Set on any ancestor to override the default 300ms:
 *
 * ```css
 * obc-gauge-horizontal {
 *   --setpoint-animation-duration: 500ms;
 * }
 * ```
 */
export declare const SETPOINT_ANIMATION_CSS_VAR = "--setpoint-animation-duration";
/** Default CSS value for the animation duration. */
export declare const SETPOINT_ANIMATION_DURATION_DEFAULT = "300ms";
/**
 * Read the effective setpoint animation duration from the element's computed CSS.
 * Returns `SETPOINT_ANIMATION_DURATION_MS` if the CSS variable is missing or unparsable.
 */
export declare function getSetpointAnimationDurationMs(el: Element): number;
/**
 * Compute the shortest angular distance between two angles.
 * Returns a value in [0, 180].
 *
 * Used for deadband comparisons (e.g. `computeAtSetpoint`) and any
 * context where you need the magnitude of the shortest arc between
 * two headings.
 */
export declare function shortestAngularDistance(from: number, to: number): number;
/**
 * Compute a CSS-safe target angle that is within ±180° of a previous
 * CSS angle, ensuring CSS `rotate()` transitions always take the
 * shortest path.
 *
 * ## Problem
 *
 * CSS `transform: rotate()` interpolates linearly between numeric
 * degree values. A transition from `rotate(350deg)` to `rotate(10deg)`
 * would animate **−340°** (the long way) instead of the intended **+20°**.
 *
 * ## Solution
 *
 * Instead of clamping to 0–360°, we accumulate an unbounded angle that
 * stays within ±180° of the last value CSS saw. CSS then always
 * interpolates the short arc.
 *
 * ## Example
 *
 * ```ts
 * cssSafeAngle(350, 10)  // → 370  (350 + 20, not 10)
 * cssSafeAngle(10, 350)  // → -10  (10 − 20, not 350)
 * cssSafeAngle(0, 181)   // → -179 (short path is −179°)
 * ```
 *
 * The resulting value can grow beyond [0, 360) but CSS handles that
 * correctly. If unbounded growth is a concern, callers can re-normalise
 * when no transition is active.
 *
 * @param prevCssAngle - The last angle value written to the CSS transform
 * @param targetAngle  - The desired angle in any range (will be normalised)
 * @returns An angle such that `|result − prevCssAngle| ≤ 180`
 */
export declare function cssSafeAngle(prevCssAngle: number, targetAngle: number): number;
/**
 * Configuration for drawing a setpoint marker.
 *
 * This interface contains ONLY design-related properties.
 * Instrument-specific logic (deadbands, state mapping) belongs in the caller.
 */
export interface DrawSetpointMarkerConfig {
    /** Which visual state to render */
    visualState: SetpointVisualState;
    /** Color palette to use (enhanced = Priority.enhanced colors, regular = Priority.regular colors) */
    colorMode: SetpointColorMode;
    /**
     * Whether the setpoint is in disabled state.
     * When true, overrides fill color to tertiary (disabled) color regardless of colorMode.
     * Typically auto-derived from InstrumentState.loading or InstrumentState.off.
     * @default false
     */
    disabled?: boolean;
    /**
     * Unique ID prefix for SVG defs (mask, etc.)
     * Required for deterministic output and to avoid conflicts when multiple
     * setpoint markers exist in the same SVG.
     *
     * Callers should generate stable IDs (e.g., based on component instance)
     * rather than random IDs to ensure SSR compatibility and snapshot stability.
     */
    id: string;
}
/**
 * Get the fill color for a setpoint marker based on visual state, color mode, and disabled state.
 *
 * Per design spec:
 * - `disabled: true`: tertiary color (overrides all other logic)
 * - `focus` state: tertiary (regular) or base-blue-100 (enhanced)
 * - All other states: primary color (no color change for equal/equalZero)
 *
 * @param visualState - The visual state of the setpoint
 * @param colorMode - The color palette to use
 * @param disabled - Whether the setpoint is in disabled state
 * @returns CSS variable string for the fill color
 */
export declare function getSetpointFillColor(visualState: SetpointVisualState, colorMode: SetpointColorMode, disabled?: boolean): string;
/**
 * Get the stroke color for setpoint marker outline.
 *
 * - Focus state: secondary (regular) or neutral-enhanced (enhanced) - visible border
 * - All other states: silhouette color (subtle outline)
 *
 * @param visualState - The visual state of the setpoint
 * @param colorMode - The color palette to use
 * @returns CSS variable string for the stroke color
 */
export declare function getSetpointStrokeColor(visualState: SetpointVisualState, colorMode: SetpointColorMode): string;
/**
 * Get the SVG path for setpoint shape based on visual state.
 *
 * All states use the filled (solid) shape.
 * Focus state is differentiated by fill color and border, not shape.
 */
export declare function getSetpointPath(_visualState: SetpointVisualState): string;
/**
 * Get the scale factor for setpoint based on visual state.
 *
 * - `equal`, `equalZero`: 80% size
 * - `notEqual`, `focus`: 100% size
 */
export declare function getSetpointScale(visualState: SetpointVisualState): number;
/**
 * Get the outward offset for setpoint marker based on visual state.
 *
 * The marker is shifted outward (away from the bar/scale) by:
 * - 8px for equalZero (to avoid overlapping with the zero position indicator)
 * - 4px for notEqual and focus (to visually separate from the scale)
 * - 0px for equal (marker sits closer to the scale)
 *
 * @param visualState - The visual state of the setpoint
 * @returns Offset in pixels
 */
export declare function getSetpointOutwardOffset(visualState: SetpointVisualState): number;
/**
 * Generate a unique ID for SVG defs (masks, etc.)
 *
 * @deprecated This function produces non-deterministic output which breaks
 * SSR hydration and snapshot tests. Callers should generate their own stable
 * IDs based on component instance or context.
 *
 * This function is kept for backward compatibility but will be removed in
 * a future version. Move ID generation to web component wrappers where
 * non-determinism is acceptable (runtime-only code).
 */
export declare function generateSetpointId(prefix?: string): string;
/**
 * Draw a setpoint marker at origin.
 *
 * Returns an SVG fragment with the marker positioned so that:
 * - The **tip is at origin (0, 0)**
 * - The **triangle points down** (positive Y direction)
 *
 * Callers must apply transforms to position and orient the marker.
 *
 * ## Transform Examples
 *
 * **Radial instrument** (marker on outer ring, pointing toward center):
 * ```ts
 * // Position at angle, then rotate 180° so tip points inward
 * svg`<g transform="rotate(${angle}) translate(0, -${radius}) rotate(180)">
 *   ${drawSetpointMarker(config)}
 * </g>`;
 * ```
 *
 * **Linear vertical, right side** (marker points left toward bar):
 * ```ts
 * // Position at (x, y), rotate -90° so tip points left
 * svg`<g transform="translate(${x}, ${y}) rotate(-90)">
 *   ${drawSetpointMarker(config)}
 * </g>`;
 * ```
 *
 * **Linear vertical, left side** (marker points right toward bar):
 * ```ts
 * // Position at (x, y), rotate 90° so tip points right
 * svg`<g transform="translate(${x}, ${y}) rotate(90)">
 *   ${drawSetpointMarker(config)}
 * </g>`;
 * ```
 *
 * **Linear horizontal, bottom** (marker points up toward bar):
 * ```ts
 * // Position at (x, y), rotate 180° so tip points up
 * svg`<g transform="translate(${x}, ${y}) rotate(180)">
 *   ${drawSetpointMarker(config)}
 * </g>`;
 * ```
 *
 * **Linear horizontal, top** (marker points down toward bar):
 * ```ts
 * // Position at (x, y), no rotation needed (default points down)
 * svg`<g transform="translate(${x}, ${y})">
 *   ${drawSetpointMarker(config)}
 * </g>`;
 * ```
 *
 * @param config - Drawing configuration
 * @returns SVG template result with marker at origin
 */
export declare function drawSetpointMarker(config: DrawSetpointMarkerConfig): SVGTemplateResult;
export type { SVGTemplateResult };
export { InstrumentState, Priority };
/**
 * Configuration for deriving setpoint visual parameters for radial instruments.
 *
 * Radial instruments (watch, compass, etc.) use a simpler API than linear instruments:
 * - No deadband/value comparison (caller provides pre-computed `atSetpoint`)
 * - No fill modes or value tracking
 * - Angle-based positioning instead of linear coordinates
 *
 * ## newAngleSetpoint Pattern
 *
 * When `newAngleSetpoint` is defined, the component renders TWO setpoint markers:
 * 1. Original `angleSetpoint` marker - dimmed (0.75 opacity), uses derived visual state
 * 2. New `newAngleSetpoint` marker - focus visual state, full opacity
 *
 * This enables the "adjustment preview" UX where users can see both the current
 * and proposed setpoint positions simultaneously.
 */
export interface RadialSetpointConfig {
    /** Current instrument state (active, loading, off) — used for disabled detection */
    state: InstrumentState;
    /**
     * Color priority mode.
     * - `Priority.enhanced`: Use enhanced (blue) color palette
     * - `Priority.regular`: Use regular (gray) color palette
     */
    priority: Priority;
    /**
     * Whether the current value equals the setpoint (within deadband).
     * Caller is responsible for deadband calculation.
     */
    atSetpoint: boolean;
    /**
     * The current setpoint angle in degrees.
     * Used to auto-derive atZero when within setpointAtZeroDeadband.
     */
    angleSetpoint?: number;
    /**
     * Deadband around zero for setpoint positioning (in degrees).
     * When |angleSetpoint| < setpointAtZeroDeadband, the setpoint is considered "at zero"
     * and triggers the equalZero visual state (80% size + outward offset).
     * @default 0.5
     */
    setpointAtZeroDeadband?: number;
    /**
     * New setpoint angle being adjusted (focus/adjustment mode).
     * When defined, indicates user is actively adjusting and triggers focus visual state.
     * The original setpoint marker will be dimmed while this is active.
     */
    newAngleSetpoint?: number;
    /**
     * Whether the user is physically interacting with the control (e.g. touching a lever).
     * When true (and `newAngleSetpoint` is undefined), the single setpoint marker
     * renders in focus visual state.
     *
     * This mirrors the linear path behavior in `deriveSetpointVisualState()` in
     * external-scale.ts, ensuring consistent focus rendering across both radial
     * and linear instruments.
     * @default false
     */
    touching?: boolean;
    /**
     * 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;
}
/**
 * Result of deriving setpoint visual parameters for radial instruments.
 */
export interface RadialSetpointDerivedConfig {
    /** Visual state for rendering (notEqual, equal, equalZero, focus) */
    visualState: SetpointVisualState;
    /** Color mode for rendering (enhanced, regular) */
    colorMode: SetpointColorMode;
    /** Whether setpoint should render in disabled state */
    disabled: boolean;
    /** Whether a newAngleSetpoint is being adjusted */
    hasNewSetpoint: boolean;
}
/**
 * Derive the visual parameters for a radial setpoint marker.
 *
 * This maps radial instrument state (from watch.ts, compass.ts, etc.)
 * to the unified setpoint visual parameters.
 *
 * ## State Mapping
 *
 * | Priority  | InstrumentState | atSetpoint | atZero | touching | → visualState       | → colorMode | → disabled |
 * |-----------|-----------------|------------|--------|----------|---------------------|-------------|------------|
 * | enhanced  | active          | false      | *      | false    | notEqual            | enhanced    | false      |
 * | enhanced  | active          | false      | *      | true     | focus               | enhanced    | false      |
 * | enhanced  | active          | true       | false  | false    | equal               | enhanced    | false      |
 * | enhanced  | active          | true       | true   | false    | equalZero           | enhanced    | false      |
 * | enhanced  | active          | *          | *      | *        | (original dimmed)   | enhanced    | false      |
 * | regular   | active          | false      | *      | false    | notEqual            | regular     | false      |
 * | regular   | active          | false      | *      | true     | focus               | regular     | false      |
 * | regular   | active          | true       | false  | false    | equal               | regular     | false      |
 * | regular   | active          | true       | true   | false    | equalZero           | regular     | false      |
 * | *         | loading         | *          | *      | *        | notEqual            | regular     | true       |
 * | *         | off             | *          | *      | *        | notEqual            | regular     | true       |
 *
 * When `setpointOverride` is true, loading/off states derive color from `priority` instead of disabling:
 *
 * | Priority  | InstrumentState | setpointOverride | → colorMode | → disabled |
 * |-----------|-----------------|------------------|-------------|------------|
 * | enhanced  | loading / off   | true             | enhanced    | false      |
 * | regular   | loading / off   | true             | regular     | false      |
 *
 * Note: When `newAngleSetpoint` is defined, the original setpoint marker is dimmed
 * and a second marker is rendered in focus state at the new position.
 *
 * @param config - Radial instrument state configuration
 * @returns Derived visual parameters for drawSetpointMarker()
 */
export declare function deriveRadialSetpointConfig(config: RadialSetpointConfig): RadialSetpointDerivedConfig;
/**
 * Default radius for radial setpoint marker positioning.
 * This is the distance from the center of the watch to the setpoint tip.
 *
 * Based on watch.ts existing behavior: `translate(-168 0)`
 * The marker is positioned at 168px from center on the outer ring.
 */
export declare const RADIAL_SETPOINT_RADIUS = 168;
/**
 * Configuration for the unified at-setpoint calculation.
 *
 * This replaces the 6+ divergent `atSetpointCalc()` implementations
 * scattered across instruments (instrument-radial, compass, heading,
 * rudder, speed-gauge, azimuth-thruster, external-scale, thruster).
 */
export interface ComputeAtSetpointConfig {
    /** Current instrument value (e.g. speed, angle, thrust) */
    value: number | undefined;
    /** Target setpoint value */
    setpoint: number | undefined;
    /**
     * User is physically interacting with the control (e.g. touching a lever).
     * When true, at-setpoint always returns false — prevents flickering
     * during real-time value changes.
     */
    touching: boolean;
    /**
     * When true (default), auto-detects at-setpoint via deadband comparison.
     * When false, uses the manual `atSetpointManual` boolean instead.
     */
    auto: boolean;
    /** Tolerance for auto at-setpoint detection */
    deadband: number;
    /**
     * Manual at-setpoint override.
     * Only used when `auto` is false.
     */
    atSetpointManual: boolean;
    /**
     * Enable 360° angular wraparound for compass-like instruments.
     * When true, distance is calculated as the shortest arc: `min(|a-b|, 360-|a-b|)`.
     * Use this for heading/compass setpoints where 359° and 1° are 2° apart.
     * @default false
     */
    angularWraparound?: boolean;
}
/**
 * Unified at-setpoint calculation.
 *
 * Replaces the divergent implementations across:
 * - `instrument-radial.ts` `atSetpointCalc()` — no wraparound, `<` comparison
 * - `compass.ts` / `heading.ts` `atHeadingSetpointCalc()` — 360° wraparound, `<`
 * - `azimuth-thruster.ts` `atAngleSetpointCalc` — no wraparound (bug), `<`
 * - `external-scale.ts` `calculateAtSetpoint()` — `<=`, no touching guard
 * - `instrument-linear.ts` / `thruster.ts` `atSetpoint()` — `<`, standalone fn
 *
 * Standardized behavior:
 * - Uses `<=` (inclusive) for deadband comparison
 * - Always checks `touching` before calculating
 * - Validates deadband with `Number.isFinite()`
 * - Supports optional 360° angular wraparound
 *
 * @param config - At-setpoint calculation parameters
 * @returns Whether the current value is at the setpoint
 *
 * @example
 * ```ts
 * // Simple linear instrument
 * computeAtSetpoint({
 *   value: 42, setpoint: 40, touching: false,
 *   auto: true, deadband: 2, atSetpointManual: false,
 * }); // → true (|42-40| = 2 <= 2)
 *
 * // Compass with wraparound
 * computeAtSetpoint({
 *   value: 359, setpoint: 1, touching: false,
 *   auto: true, deadband: 3, atSetpointManual: false,
 *   angularWraparound: true,
 * }); // → true (angular distance = 2 <= 3)
 * ```
 */
export declare function computeAtSetpoint(config: ComputeAtSetpointConfig): boolean;
//# sourceMappingURL=setpoint.d.ts.map