/**
 * `<code-ui>` — Syntax-highlighted code block (CodeMirror 6 under the hood).
 *
 * @see https://ui-kit.exe.xyz/site/components/code
 */

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

export interface CodeChangeEventDetail {
  value: string;
}
export type CodeChangeEvent = CustomEvent<CodeChangeEventDetail>;
export type CodeInputEvent = CustomEvent<CodeChangeEventDetail>;

/**
 * Detail payload for the `save` event — fired when the user invokes the
 * CodeMirror save keybinding (Cmd/Ctrl+S). The event is `cancelable: true`;
 * call `event.preventDefault()` to suppress the host page's save handling.
 */
export interface CodeSaveEventDetail {
  /** Current editor contents at the moment of save. */
  value: string;
}
export type CodeSaveEvent = CustomEvent<CodeSaveEventDetail>;

/**
 * Detail payload for the `language-load-error` event — fired when
 * CodeMirror's dynamic language-mode import fails. `phase: "core"`
 * indicates the CodeMirror core bundle itself failed (rare, fatal —
 * the component falls back to a static `<pre><code>`). `phase: "language"`
 * indicates the requested language extension failed (recoverable —
 * editor still mounts in plain-text mode).
 */
export interface CodeLanguageLoadErrorEventDetail {
  phase: 'core' | 'language';
  /** Present when `phase === 'language'`; the language slug that failed. */
  language?: string;
  /** The underlying load failure. */
  error: unknown;
}
export type CodeLanguageLoadErrorEvent = CustomEvent<CodeLanguageLoadErrorEventDetail>;

/**
 * `<code-ui>` — syntax-highlighted code block (CodeMirror 6 under the hood).
 *
 * Three content-source paths in priority order:
 *
 *   1. `[text]` attribute — reactive, programmatic; updates re-render the block.
 *
 *   2. `<template>` child — escape-free authoring path (v0.5.x §329). Author
 *      the source with literal `<` / `>` (the HTML parser treats `<template>`
 *      content as inert; it lives in a `DocumentFragment` instead of being
 *      upgraded into DOM elements). The wrapper indent is dedented so the
 *      inner block reads at column 0.
 *
 *      ```html
 *      <code-ui language="html">
 *        <template>
 *          <nav-ui>
 *            <nav-item-ui text="Home"></nav-item-ui>
 *          </nav-ui>
 *        </template>
 *      </code-ui>
 *      ```
 *
 *   3. Authored textContent — original path. HTML samples require entity
 *      escaping (`&lt;`/`&gt;`/`&amp;`), same constraint as `<pre><code>`,
 *      since the parser treats unescaped tags as child elements.
 */
export class UICode extends UIFormElement {
  /** CodeMirror language slug — `javascript` / `typescript` / `html` / `css` / `json` / `markdown` / `python` etc. */
  language: string;
  /** Inline mode — drops chrome, renders as a single-line code fragment. */
  inline: boolean;
  /** Text content of the code block (alternative to slotted children). */
  text: string;
  /** Alias for `text` — set via `el.textContent` round-trips. */
  textContent: string;
  /** Show line numbers in the gutter. */
  lineNumbers: boolean;
  /** Editable mode — user can type. Form-associated only when this is true. */
  editable: boolean;
  /** Drop chrome (border, background) for inline composition. */
  bare: boolean;
  placeholder: string;
  /** §207 (v0.5.7): native form-element name for `<form>` submission. */
  name: string;
  /** §207 (v0.5.7): form-validity `required` flag. */
  required: boolean;
  /** §207 (v0.5.7): native `disabled` flag — suppresses input + form submission. */
  disabled: boolean;
  /** §207 (v0.5.7): readonly mode — user cannot type but value is form-submitted. */
  readonly: boolean;

  addEventListener<K extends keyof HTMLElementEventMap>(
    type: K,
    listener: (this: UICode, ev: HTMLElementEventMap[K]) => unknown,
    options?: boolean | AddEventListenerOptions,
  ): void;
  addEventListener(type: 'change', listener: (ev: CodeChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'input', listener: (ev: CodeInputEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'save', listener: (ev: CodeSaveEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
  addEventListener(type: 'language-load-error', listener: (ev: CodeLanguageLoadErrorEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
}
