/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
/** @jsx h */
/** @jsxFrag Fragment */

import { Fragment, h, render } from "../preact/mod.tsx";
import { useCallback, useState, useMemo, useEffect, useRef } from "../preact/hooks.ts";
import { useSelection } from "./useSelection.ts";
import { useSearch } from "./useSearch.ts";
import { selections } from "../scrapbox-userscript-std/dom.ts";

export interface Options {
  /** 表示する最大候補数
   *
   * @default 5
   */
  limit?: number;
}

const App = ({ limit }: Options) => {
  const { text, range } = useSelection();
  const ref = useRef<HTMLDivElement>(null); // 座標計算用
  
  const style = useMemo<h.JSX.CSSProperties>(() => {
    // 一行だけ選択している時のみ表示する
    if (text === "" || text.includes("\n") || !ref.current) {
      return { display: "none" };
    }
    
    // 座標を取得する
    const root = ref.current.parentNode;
    if (!(root instanceof ShadowRoot)) {
      throw Error(`The parent of "div.container" must be ShadowRoot`);
    }
    /** 基準座標 */
    const parentRect = root.host?.parentElement?.getBoundingClientRect?.();
    /** 選択範囲の座標 */
    const rect = selections()?.lastElementChild?.getBoundingClientRect?.();
    if (!rect || !parentRect) return { display: "none" };
    
    return {
      top: `${rect.bottom - parentRect.top}px`,
      left: `${(rect.left - parentRect.left)}px`,
    };
  }, [text, range]); // 選択範囲のサイズ変更でも再計算するために、rangeを依存配列に加えている
  
  const candidates = useSearch(text, limit ?? 5);
  
  return (<>
    <style>{`
      .container {
        position: absolute;
        max-width: 80vw;
        max-height: 80vh;
        margin-top: 14px;
        overflow-x: hidden;
        overflow-y: auto;
        z-index: 1000;
        
        background-color: var(--dropdown-menu-bg, #fff);
        color: var(--dropdown-menu-text-color, #333);
        border: var(--dropdown-menu-border, 1px solid rgba(0,0,0,.15));
        border-radius: 4px;
        box-shadow: 0 6px 12px rgba(0,0,0,.175);
      }
    `}</style>
    <div ref={ref} className="container" style={style}>
      {candidates.map((title) => (
        <div key={title} className="candidate" title={title}>{title}</div>
      ))}
    </div>
  </>);
};

const app = document.createElement("div");
const shadowRoot = app.attachShadow({ mode: "open" });
document.body.append(app);
render(<App limit={10} />, shadowRoot);
