import { createBinding } from "../core/signals"
import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type TextStyle, type UIElementBase } from "./UINode"

export type UITextStyle = ElementStyle & TextStyle & DrawableStyle

/** A text label. */
export interface UIText extends UIElementBase<UITextStyle, DrawableStyle & BaseStyle & TextStyle> {
  readonly type: "text",
  /** The displayed string — writable at any time. */
  text: string,
}

export class TextElement extends Element<"text"> {
  private _text: string
  constructor(style: any, text: string | (() => string)) {
    super("text", style)
    if (typeof text === "function") {
      // Reactive content: re-runs when a signal `text()` read changes; the setter routes to
      // _creatorUI.updateNode when mounted and just keeps _text current when not.
      this._text = ""
      createBinding(this, "#text", () => {
        const value = text()
        if (value !== this._text) this.text = value
      })
    } else {
      this._text = text
    }
  }
  get text(): string {
    return this._text
  }
  set text(value) {
    this._text = value
    if (this._id !== 0) {
      _creatorUI.updateNode(this._id, "text", value)
    }
  }
}

/** Create a text label — a string, or `() => string` for reactive text that re-renders when a
 *  signal it read changes. */
export function UIText(text: string | (() => string)): UIText;
/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
export function UIText(style: UITextStyle, text: string | (() => string)): UIText;
export function UIText(...args: [string | (() => string)] | [UITextStyle, string | (() => string)]): UIText {
  if (args.length === 1) {
    return new TextElement({}, args[0])
  } else {
    return new TextElement(args[0], args[1])
  }
}
