/**
 * `<list-window-ui>` — Virtualized / windowed list primitive. Renders only the visible slice of a large items[] array (chat threads, feeds, log streams, nav lists, search-result panes) — typically ≤50 DOM rows regardless of the underlying collection size. Composes a `render`-function prop OR a slotted <template> for row materialization; ships a fixed-size fast-path (constant-time index→offset math) and a variable-size measurement fallback. Distinct from <list-ui> (renders every child, preferred for short lists < 50 items) and <table-ui> (tabular data with columns). Use list-window-ui when items.length is large enough that rendering every row would block the main thread or stutter scroll.
 *
 * @see https://ui-kit.exe.xyz/site/components/list-window
 *
 * 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 ListWindowItemClickEventDetail {
  /** Item index in the full items[] array. */
  index: number;
  /** The clicked item (full item-shape from items[]). */
  item: string;
}

export type ListWindowItemClickEvent = CustomEvent<ListWindowItemClickEventDetail>;
export interface ListWindowMeasureEventDetail {
  /** Measured row height in pixels. */
  height: number;
  /** Index of the row that was measured. */
  index: number;
}

export type ListWindowMeasureEvent = CustomEvent<ListWindowMeasureEventDetail>;
export interface ListWindowRangeChangeEventDetail {
  /** The items currently materialized in the window. */
  items: unknown[];
  /** Last rendered row index (exclusive). */
  endIndex: number;
  /** First rendered row index. */
  startIndex: number;
}

export type ListWindowRangeChangeEvent = CustomEvent<ListWindowRangeChangeEventDetail>;
export interface ListWindowScrollEndEventDetail {
  /** Last visible row index. */
  index: number;
}

export type ListWindowScrollEndEvent = CustomEvent<ListWindowScrollEndEventDetail>;
export interface ListWindowScrollStartEventDetail {
  /** First visible row index. */
  index: number;
}

export type ListWindowScrollStartEvent = CustomEvent<ListWindowScrollStartEventDetail>;

export class UIListWindow extends UIElement {
  /** The items to virtualize. Required for prop-driven authoring; ignored when data-stream-src is set. */
  items: unknown[];
  /** Scroll axis — vertical (default) or horizontal carousel. */
  direction: 'vertical' | 'horizontal';
  /** Initial guess for variable-height rows. Used until the first measurement pass refines the offset cache. */
  estimatedSize: number;
  /** Fixed item height in pixels. When > 0, uses the constant-time fast path (avoids per-row measurement). */
  itemSize: number;
  /** Fixed item height in rem. Useful for typographic-scale rows that should track the body type. */
  itemSizeRem: number;
  /** Render skeleton rows in the visible window. Sets aria-busy="true" on the host. */
  loading: boolean;
  /** Rows to render above + below the visible window. 0–20 is reasonable; > 50 negates the windowing benefit. */
  overscan: number;
  /** When appending items, keep scroll pinned to the bottom (chat-thread / log-tail pattern). */
  pinBottom: boolean;
  /** Index to scroll to on mount. Useful for restoring scroll position on remount. */
  startIndex: number;

  addEventListener<K extends keyof HTMLElementEventMap>(
    type: K,
    listener: (this: UIListWindow, ev: HTMLElementEventMap[K]) => unknown,
    options?: boolean | AddEventListenerOptions,
  ): void;
  addEventListener(type: 'item-click', listener: (ev: ListWindowItemClickEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'measure', listener: (ev: ListWindowMeasureEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'range-change', listener: (ev: ListWindowRangeChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'scroll-end', listener: (ev: ListWindowScrollEndEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'scroll-start', listener: (ev: ListWindowScrollStartEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
}
