import { ContainerElement, type AnimateStyle, type AppearStyle, type ChildrenFn, type ContainerStyle, type DisappearStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type Style, type StyleFn, type UINode, type UINodeChild } from "./UINode"

export type UIContainerStyle = ElementStyle & DrawableStyle & ContainerStyle

export interface UIColumn {
  readonly type: "column",
  style: Style<this, UIContainerStyle>,
  animateTo: AnimateStyle<this, UIContainerStyle>
  animateFrom: AnimateStyle<this, UIContainerStyle>

  append(...nodes: UINodeChild[]): UIColumn
  insert(index: number, ...nodes: UINodeChild[]): UIColumn
  remove(...nodes: UINodeChild[]): UIColumn
  setContent(nodes: UINodeChild[] | ChildrenFn): this
  
  onLayout(onLayout: OnLayoutCallback): this

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

  readonly children: UINodeChild[]
}
export function UIColumn(): UIColumn
export function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn
export function UIColumn(style: UIContainerStyle): UIColumn
export function UIColumn(style: UIContainerStyle, children: UINodeChild[]): UIColumn
export function UIColumn(...args: [] | [UINodeChild[] | ChildrenFn | UIContainerStyle] | [UIContainerStyle, children: UINodeChild[] | ChildrenFn]): UIColumn {
  if (args.length === 0) {
    return new ContainerElement("column", {}, [])
  } else if (args.length === 1) {
    if (Array.isArray(args[0]) || typeof args[0] === "function") {
      return new ContainerElement("column", {}, args[0])
    } else {
      return new ContainerElement("column", args[0], [])
    }
  } else {
    return new ContainerElement("column", args[0], args[1])
  }
}

export interface UIRow {
  readonly type: "row",
  style: Style<this, UIContainerStyle>,
  animateTo: AnimateStyle<this, UIContainerStyle>,
  animateFrom: AnimateStyle<this, UIContainerStyle>,

  append(...nodes: UINodeChild[]): UIRow
  insert(index: number, ...nodes: UINodeChild[]): UIRow
  remove(...nodes: UINodeChild[]): UIRow
  setContent(nodes: UINodeChild[] | ChildrenFn): this

  onLayout(onLayout: OnLayoutCallback): this

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

  readonly children: UINodeChild[],
}
export function UIRow(children: UINodeChild[] | ChildrenFn): UIRow
export function UIRow(style: UIContainerStyle): UIRow
export function UIRow(style: UIContainerStyle, children: UINodeChild[]): UIRow
export function UIRow(...args: [] | [UINodeChild[] | ChildrenFn | UIContainerStyle] | [UIContainerStyle, children: UINodeChild[] | ChildrenFn]): UIRow {
  if (args.length === 0) {
    return new ContainerElement("row", {}, [])
  } else if (args.length === 1) {
    if (Array.isArray(args[0]) || typeof args[0] === "function") {
      return new ContainerElement("row", {}, args[0])
    } else {
      return new ContainerElement("row", args[0], [])
    }
  } else {
    return new ContainerElement("row", args[0], args[1])
  }
}

export interface UIBox {
  readonly type: "box",
  style: Style<this, UIContainerStyle>,
  animateTo: AnimateStyle<this, UIContainerStyle>,
  animateFrom: AnimateStyle<this, UIContainerStyle>,

  append(...nodes: UINodeChild[]): this
  insert(index: number, ...nodes: UINodeChild[]): this
  remove(...nodes: UINodeChild[]): this
  setContent(nodes: UINodeChild[] | ChildrenFn): this

  onLayout(onLayout: OnLayoutCallback): this

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

  readonly children: UINodeChild[],
}
export function UIBox(children: UINodeChild[] | ChildrenFn): UIBox
export function UIBox(style: UIContainerStyle): UIBox
export function UIBox(style: UIContainerStyle, children: UINodeChild[]): UIBox
export function UIBox(...args: [] | [UINodeChild[] | ChildrenFn | UIContainerStyle] | [UIContainerStyle, children: UINodeChild[] | ChildrenFn]): UIBox {
  if (args.length === 0) {
    return new ContainerElement("box", {}, [])
  } else if (args.length === 1) {
    if (Array.isArray(args[0]) || typeof args[0] === "function") {
      return new ContainerElement("box", {}, args[0])
    } else {
      return new ContainerElement("box", args[0], [])
    }
  } else {
    return new ContainerElement("box", args[0], args[1])
  }
}
