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

export type UITextStyle = ElementStyle & TextStyle

export interface UIText {
  readonly type: "text",
  text: string,
  style: Style<this, UITextStyle>,
  animateTo: AnimateStyle<this, DrawableStyle & BaseStyle & TextStyle>
  animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle & TextStyle>

  onLayout(onLayout: OnLayoutCallback): this

  setClass(name: string, enabled: boolean): this
  toggleClass(name: string): this
  hasClass(name: string): boolean
  bindClass(name: string, fn: () => boolean): this
}

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)
    }
  }
}

export function UIText(text: string | (() => string)): UIText;
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])
  }
}
