/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
import { Item, makeGroup } from "./item.ts";
import { Cursor, Selection, takeStores } from "../scrapbox-userscript-std/dom.ts";
import type { Scrapbox } from "../scrapbox-jp%2Ftypes/userscript.ts";
declare const scrapbox: Scrapbox;

const { cursor, selection } = takeStores();

/** ボタンの設定 */
export interface Button {
  /** .status-bar > div につけるclass name */
  className?: string;
  /** ボタンに表示するアイテム
   *
   * 空文字を渡すと非表示になる
   *
   * 函数系は、カーソルが動くたびに呼び出される
   */
  display: Item | Item[] | ((props: Omit<ClickProps, "setDisplay">) => Item | Item[]);
  onClick: (props: ClickProps) => void;
  /** ボタンを表示するページの種類
   *
   * トップページやstreamなど、特殊なページで使いたいボタンがあれば指定する
   *
   * @default "page"
   */
  context?: Context;
};
export interface ClickProps {
  cursor: Cursor;
  selection: Selection; 
  setDisplay: (...items: Item[]) => void;
}
export type Context = "page" | "stream" | "list";

/** ボタンの描画情報 */
export interface ButtonComponent {
  status: HTMLDivElement;
  context: Context;
  update: () => void;
}

export const makeButton = (init: Button): ButtonComponent => {
  const { className, display, onClick, context = "page" } = init;
  const status = document.createElement("div");
  if (className) status.classList.add(className);
  if (!isContext(context)) status.style.display = "none";
  
  const setDisplay = (...items: Item[]) => {
    // 空文字の場合は非表示にする
    if (items.length === 1 && items[0] === "") {
      status.style.display = "none";
      return;
    }
    status.textContent = "";
    const group = makeGroup(...items);
    if (group) status.append(group);
  };
  const itemList = typeof display === "function" ? display({ cursor, selection }) : display;
  setDisplay(...(Array.isArray(itemList) ? itemList : [itemList]));
  status.addEventListener("click", (e) => {
    e.preventDefault();
    e.stopPropagation();
    onClick({ cursor, selection, setDisplay });
  });
  
  const update = () => {
    if (isContext(context)) {
      status.removeAttribute("style");
    } else {
      status.style.display = "none";
    }
    if (typeof display === "function") {
      const itemList = display({ cursor, selection });
      setDisplay(...(Array.isArray(itemList) ? itemList : [itemList]));
    }
  };
  
  return { status, context, update };
};

const isContext = (context: Context): boolean => 
  context !== "stream" ?
    scrapbox.Layout === context :
    scrapbox.Layout === "list" && location.pathname.startsWith("/stream");