/**
 * `<color-picker-ui>` — OKLCH-native color picker with 2D area + H/C/L sliders.
 *
 * Form-associated (extends UIFormElement). The `[format]` attribute controls
 * whether `value` is read/written as a `#rrggbb` hex string or an `oklch(L C H)`
 * string, but the event detail always carries BOTH forms plus the parsed
 * OKLCH channel scalars — consumers don't need to parse the string.
 *
 * @see https://ui-kit.exe.xyz/site/components/color-picker
 */

import { UIFormElement } from '../../core/form.js';

/**
 * Output format selected by the `[format]` attribute. Drives the shape of
 * `value` (and the matching `detail.value` field). Both `hex` and `oklch`
 * forms are always present on the event detail regardless of `[format]`.
 */
export type ColorFormat = 'hex' | 'oklch';

/**
 * Detail payload for both `change` (commit) and `input` (continuous drag)
 * events. Carries parsed channel scalars + both string forms — `value`
 * mirrors the picker's current `[format]`, while `hex` and `oklch` are
 * always populated parallel views.
 */
export interface ColorPickerChangeEventDetail {
  /** Format-respecting string. Equals `hex` when `[format="hex"]`; equals `oklch` when `[format="oklch"]`. */
  value: string;
  /** OKLCH lightness (0–1). */
  l: number;
  /** OKLCH chroma (0–~0.4). */
  c: number;
  /** OKLCH hue (0–360, degrees). */
  h: number;
  /** Hex string (`#rrggbb`). Gamut-mapped to sRGB. */
  hex: string;
  /** OKLCH string (`oklch(L C H)`, fixed precision). */
  oklch: string;
}
export type ColorPickerChangeEvent = CustomEvent<ColorPickerChangeEventDetail>;
export type ColorPickerInputEvent = CustomEvent<ColorPickerChangeEventDetail>;

/**
 * Axis-specific clamp record. Fires when a consumer-declared constraint
 * (max-chroma / max-l / min-l / hue-drift-max) clamped a user-requested
 * channel value to its in-bound equivalent.
 */
export interface ColorPickerClampRecord {
  /** OKLCH axis that was clamped. */
  axis: 'l' | 'c' | 'h';
  /** Channel value the user requested before the clamp. */
  requested: number;
  /** Channel value the picker actually committed after the clamp. */
  clamped: number;
  /** Constraint prop that triggered the clamp. */
  reason: 'max-l' | 'min-l' | 'max-chroma' | 'hue-drift-max';
}

/**
 * Detail payload for the `constraint-clamp` event — fired immediately
 * before the corresponding `change` / `input` when one or more axes
 * were clamped to fit the consumer's declared constraints. `clamps`
 * is never empty.
 */
export interface ColorPickerConstraintClampEventDetail {
  clamps: ColorPickerClampRecord[];
}
export type ColorPickerConstraintClampEvent = CustomEvent<ColorPickerConstraintClampEventDetail>;

export class UIColorPicker extends UIFormElement {
  /** Form field name. */
  name: string;
  /** Disables all interaction. */
  disabled: boolean;
  /** Current color as a string in the active `format`. */
  value: string;
  /** Output format — drives the shape of `value`. Detail always carries both `hex` and `oklch`. */
  format: ColorFormat;
  /** Clamp the OKLCH chroma channel to at most this value. `Infinity` = unconstrained. */
  maxChroma: number;
  /** Clamp the OKLCH lightness channel to at most this value (0..1). `1` = unconstrained. */
  maxL: number;
  /** Clamp the OKLCH lightness channel to at least this value (0..1). `0` = unconstrained. */
  minL: number;
  /** Maximum allowed signed-shortest-path hue drift in degrees from `baseHue`. `NaN` = unconstrained. */
  hueDriftMax: number;
  /** Reference hue (degrees) for the `hueDriftMax` constraint. `NaN` = use the picker's hue at first commit. */
  baseHue: number;

  addEventListener<K extends keyof HTMLElementEventMap>(
    type: K,
    listener: (this: UIColorPicker, ev: HTMLElementEventMap[K]) => unknown,
    options?: boolean | AddEventListenerOptions,
  ): void;
  addEventListener(type: 'change', listener: (ev: ColorPickerChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'input', listener: (ev: ColorPickerInputEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'constraint-clamp', listener: (ev: ColorPickerConstraintClampEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
}
