/**
 * `<combobox-ui>` — Typeahead-filterable single-select primitive — the constrained-choice
combobox per WAI-APG "Combobox With List Autocomplete (manual
selection)". The committed value MUST come from the options list
unless `[free-text]` is set. Distinct from `<select-ui searchable>`
(button-first dropdown) and `<autocomplete-input-ui>` (free-form).
Form-bearing via UIFormElement: `[name]`, `[value]`, `[required]`,
`[disabled]`, fires `change`. Options via native `<option>` /
`<optgroup>` children OR programmatic `.options` array.

 *
 * @see https://ui-kit.exe.xyz/site/components/combobox
 *
 * Type declarations generated by scripts/build/dts-codegen.mjs from
 * the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
 * run `npm run build:components`, then `npm run codegen:dts` to
 * regenerate; or hand-author this file fully if rich event types are
 * needed beyond what the yaml `events:` block can express.
 */

import { UIElement } from '../../core/element.js';

export interface ComboboxChangeEventDetail {
  /** Resolved option object or null when free-text / cleared. */
  option: Record<string, unknown>;
  /** One of `click` / `keyboard` / `programmatic`. */
  source: string;
  /** Committed value. */
  value: string;
}

export type ComboboxChangeEvent = CustomEvent<ComboboxChangeEventDetail>;
export interface ComboboxCloseEventDetail {
  /** One of `escape` / `outside` / `select` / `blur`. */
  reason: string;
}

export type ComboboxCloseEvent = CustomEvent<ComboboxCloseEventDetail>;
export interface ComboboxCreateEventDetail {
  /** The typed text the user is trying to create. */
  value: string;
}

export type ComboboxCreateEvent = CustomEvent<ComboboxCreateEventDetail>;
export interface ComboboxInputEventDetail {
  /** Lowercased filter query. */
  query: string;
  /** Current input text (the user's typed query). */
  value: string;
}

export type ComboboxInputEvent = CustomEvent<ComboboxInputEventDetail>;
export interface ComboboxInvalidEventDetail {
  /** The unmatched typed text. */
  query: string;
}

export type ComboboxInvalidEvent = CustomEvent<ComboboxInvalidEventDetail>;
export interface ComboboxOpenEventDetail {
  /** One of `click` / `keyboard` / `typing`. */
  trigger: string;
}

export type ComboboxOpenEvent = CustomEvent<ComboboxOpenEventDetail>;

export class UICombobox extends UIElement {
  /** Marks the field as required for form validation */
  required: boolean;
  /** Renders an `x` clear button when value is set */
  clearable: boolean;
  /** Implies `[free-text]`; on Enter with unmatched typed text fires a
`create` event with detail.value so the consumer can run a
backend create-then-refresh-options flow. */
  creatable: boolean;
  /** Disables interaction and dims the control */
  disabled: boolean;
  /** Validation error message */
  error: string;
  /** Caption text below the field; wires `aria-describedby` on the host
so screen readers announce it as a description. */
  hint: string;
  /** Inline label rendered above the field. Wrap with <field-ui> for
proper `<label for>` association in form-row compositions. */
  label: string;
  /** Shows a loading spinner inside the popover; consumer drives async fetch */
  loading: boolean;
  /** Form control name for form data submission */
  name: string;
  /** Reflects popover open / closed state */
  open: boolean;
  /** Programmatic option list. Array of {value, label, disabled?, group?} or grouped {label, options:[…]}. Alternative to declarative <option> / <optgroup> children. */
  options: unknown[];
  /** Placeholder text in the input when value is empty */
  placeholder: string;
  /** Prevents selection changes while keeping the field focusable + popover-open allowed */
  readonly: boolean;
  /** Sizing scale via universal `[size]` attribute system. Matches Input + Select sizing tokens so a Combobox rendered alongside either feels coherent in a form row. */
  size: 'sm' | 'md' | 'lg';
  /** Currently selected option value. Must be a member of `options[].value` unless `[free-text]` is set. With declarative <option> children, a child carrying the native `selected` attribute sets the initial value when this attribute is absent. */
  value: string;

  addEventListener<K extends keyof HTMLElementEventMap>(
    type: K,
    listener: (this: UICombobox, ev: HTMLElementEventMap[K]) => unknown,
    options?: boolean | AddEventListenerOptions,
  ): void;
  addEventListener(type: 'change', listener: (ev: ComboboxChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'close', listener: (ev: ComboboxCloseEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'create', listener: (ev: ComboboxCreateEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'input', listener: (ev: ComboboxInputEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'invalid', listener: (ev: ComboboxInvalidEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'open', listener: (ev: ComboboxOpenEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
}
