/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
/** @jsx h */
/** @jsxFrag Fragment */
import { Fragment, h, render } from "https://esm.sh/preact@10.6.4";
import {
  useCallback,
  useMemo,
  useState,
} from "https://esm.sh/preact@10.6.4/hooks";
import { Asearch, MatchResult } from "../deno-asearch/mod.ts";
import { data } from "./data.ts";
import { getMaxDistance } from "./distance.ts";

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

let remove: () => void;

const App = () => {
  const [pattern, setPattern] = useState("");
  const candidates = useMemo(
    () => {
      const match = Asearch(` ${pattern} `).match;
      const len = pattern.length;
      if (len === 0) return [];
      
      const maxDistance = getMaxDistance[len];
      const candidates = data.flatMap(
          (candidate) => {
            const result = match(candidate, maxDistance);
            if (!result.found) return [];
            return { candidate, distance: result.distance };
          }
        )
      /*const candidates = scrapbox.Project.pages.flatMap(
          (page) => {
            const result = match(page.title, maxDistance);
            if (!result.found) return [];
            return { candidate: page.title, distance: result.distance, updated: page.updated, };
          }
        )*/
        // 1. 編集距離 2. 文字列超 3. 辞書順序 が小さい順に並び替える
        .sort((a, b) => {
          const diff = a.distance - b.distance;
          if (diff !== 0) return diff;
          //const time = b.updated - a.updated;
          //if (time !== 0) return time;
          const lenDiff = a.candidate.length - b.candidate.length;
          if (lenDiff !== 0) return lenDiff;
          return a.candidate.localeCompare(b.candidate);
        });
      return candidates;
    },
    [pattern],
  );

  const handlePattern = useCallback(
    (e: h.JSX.TargetedEvent<HTMLInputElement>) =>
      setPattern(e.currentTarget.value.trim()),
    [],
  );

  return (
    <>
      <style>
        {`
      :host {
        position: fixed;
        top: 60px;
        left: 50%;
        transform: translate(-50%, 0);
        padding: 5px;
        border: 1px solid lime;
        border-radius: 5px;
        font-size: 14px;
        background-color: var(--page-bg);
        color: var(--page-text-color);
      }
      input {
        min-width: 40%;
      }
      button {
       position: absolute;
       top: 0px;
       right: 0px;
      }
    `}
      </style>
      <button onClick={remove}>x</button>
      <p>
        <label>
          pattern: <input type="text" value={pattern} onInput={handlePattern} />
        </label>
      </p>
      <p>
        {candidates.length > 0 ? `Matched ${candidates.length} words` : "No matched"}
        <br />
        <ul>
          {candidates.map(({ candidate }) => (<li>{candidate}</li>))}
        </ul>
      </p>
    </>
  );
};
