/* Global docs search — a ⌘K / Ctrl-K command palette shared by every page
 * under examples/docs/. Pure client-side, no build step at runtime: it reads
 * the prebuilt window.SEEK_DOCS_INDEX (search-index.js, generated by
 * `go run ./scripts/gendocssearch`) and searches page titles + section
 * headings (bilingual). Loaded via <script src> so it also works on file://.
 *
 * Per-page footprint is just two <script defer> tags; this file injects its
 * own CSS, the trigger button (into .util-bar), and the modal DOM. */
(function () {
  "use strict";

  var INDEX = window.SEEK_DOCS_INDEX;
  if (!Array.isArray(INDEX) || INDEX.length === 0) return;

  var MAX_RESULTS = 12;
  var lastFocused = null;
  var open = false;
  var active = 0;
  var current = []; // current result list

  function lang() {
    try { return localStorage.getItem("seek-lang") === "zh" ? "zh" : "en"; }
    catch (e) { return "en"; }
  }
  function titleOf(p) {
    return lang() === "zh" ? (p.title || p.titleEn) : (p.titleEn || p.title);
  }

  // ---- styles (use the page's own CSS variables so it themes light/dark) ----
  var css =
    ".sk-overlay{position:fixed;inset:0;z-index:9999;display:flex;align-items:flex-start;" +
    "justify-content:center;padding:12vh 16px 16px;background:rgba(0,0,0,.55);" +
    "-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}" +
    ".sk-overlay[hidden]{display:none}" +
    ".sk-panel{width:min(640px,94vw);max-height:76vh;display:flex;flex-direction:column;" +
    "background:var(--surface,#12121a);border:1px solid var(--border,#1e1e2a);border-radius:10px;" +
    "overflow:hidden;box-shadow:0 16px 48px rgba(0,0,0,.55)}" +
    ".sk-inputrow{display:flex;align-items:center;gap:10px;padding:14px 16px;" +
    "border-bottom:1px solid var(--border,#1e1e2a)}" +
    ".sk-inputrow svg{width:18px;height:18px;color:var(--dim,#8a8a98);flex-shrink:0}" +
    ".sk-input{flex:1;background:transparent;border:none;outline:none;color:var(--text,#d0d0d8);" +
    "font:500 1rem/1.4 var(--font-display,ui-monospace,Menlo,monospace)}" +
    ".sk-input::placeholder{color:var(--dim,#8a8a98)}" +
    ".sk-results{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}" +
    ".sk-item{padding:9px 12px;border-radius:6px;cursor:pointer;border-left:2px solid transparent}" +
    ".sk-item[aria-selected=true]{background:var(--hover-bg,rgba(255,255,255,.05));" +
    "border-left-color:var(--amber,#f5a623)}" +
    ".sk-item .sk-t{color:var(--text,#d0d0d8);font:600 .92rem/1.3 var(--font-display,monospace)}" +
    ".sk-item .sk-s{color:var(--dim,#8a8a98);font-size:.74rem;margin-top:2px}" +
    ".sk-item .sk-s b{color:var(--teal,#00d4ff);font-weight:600}" +
    ".sk-empty{padding:20px 16px;color:var(--dim,#8a8a98);font-size:.85rem;text-align:center}" +
    ".sk-foot{display:flex;gap:14px;padding:8px 14px;border-top:1px solid var(--border,#1e1e2a);" +
    "font-size:.7rem;color:var(--dim,#8a8a98)}" +
    ".sk-foot kbd{font-family:var(--font-display,monospace);border:1px solid var(--border,#1e1e2a);" +
    "border-radius:4px;padding:0 5px}" +
    ".sk-trigger{display:inline-flex;align-items:center;gap:6px;height:44px;padding:0 12px;" +
    "border:1px solid var(--border,#1e1e2a);border-radius:4px;background:transparent;cursor:pointer;" +
    "color:var(--dim,#8a8a98);font:500 .8rem var(--font-display,monospace);transition:all .2s}" +
    ".sk-trigger:hover{border-color:var(--amber,#f5a623);color:var(--amber,#f5a623)}" +
    ".sk-trigger svg{width:15px;height:15px}" +
    ".sk-trigger kbd{font-family:inherit;font-size:.72rem;opacity:.8}" +
    "@media (max-width:600px){.sk-trigger kbd{display:none}}" +
    "@media (prefers-reduced-motion:reduce){.sk-trigger{transition:none}}";

  var SEARCH_SVG =
    '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" ' +
    'stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
    '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>';

  var overlay, input, results;

  function build() {
    var style = document.createElement("style");
    style.id = "sk-search-css";
    style.textContent = css;
    document.head.appendChild(style);

    overlay = document.createElement("div");
    overlay.className = "sk-overlay";
    overlay.hidden = true;
    overlay.setAttribute("role", "dialog");
    overlay.setAttribute("aria-modal", "true");
    overlay.setAttribute("aria-label", "Search documentation");
    overlay.innerHTML =
      '<div class="sk-panel">' +
        '<div class="sk-inputrow">' + SEARCH_SVG +
          '<input class="sk-input" type="search" autocomplete="off" spellcheck="false" ' +
          'role="combobox" aria-expanded="true" aria-controls="sk-results" ' +
          'aria-label="Search documentation" placeholder="Search docs… (titles & sections)">' +
        "</div>" +
        '<ul class="sk-results" id="sk-results" role="listbox"></ul>' +
        '<div class="sk-foot"><span><kbd>↑</kbd><kbd>↓</kbd> navigate</span>' +
        "<span><kbd>↵</kbd> open</span><span><kbd>esc</kbd> close</span></div>" +
      "</div>";
    document.body.appendChild(overlay);
    input = overlay.querySelector(".sk-input");
    results = overlay.querySelector(".sk-results");

    overlay.addEventListener("mousedown", function (e) {
      if (e.target === overlay) close(); // click backdrop
    });
    input.addEventListener("input", function () { render(input.value); });
    input.addEventListener("keydown", onInputKey);

    // trigger button in the util-bar (falls back to keyboard-only if absent)
    var bar = document.querySelector(".util-bar");
    if (bar) {
      var btn = document.createElement("button");
      btn.className = "sk-trigger";
      btn.type = "button";
      btn.setAttribute("aria-haspopup", "dialog");
      btn.setAttribute("aria-label", "Search documentation (Command K)");
      btn.innerHTML = SEARCH_SVG +
        '<span data-lang="en">Search</span><span data-lang="zh" hidden>搜索</span><kbd>⌘K</kbd>';
      btn.addEventListener("click", openSearch);
      bar.insertBefore(btn, bar.firstChild);
      // Set initial language (the button is injected after the page's own
      // setLang ran); later toggles are handled by the page's [data-lang] sweep.
      var l = lang();
      btn.querySelectorAll("[data-lang]").forEach(function (s) {
        s.hidden = s.getAttribute("data-lang") !== l;
      });
    }
    input.placeholder = lang() === "zh"
      ? "搜索文档…（标题与章节）"
      : "Search docs… (titles & sections)";
  }

  // ---- search ----
  function score(p, terms) {
    var t = ((p.title || "") + " " + (p.titleEn || "")).toLowerCase();
    var hs = (p.headings || []).map(function (h) { return h.toLowerCase(); });
    var hayHead = hs.join(" \n ");
    var s = 0, matchedHeading = "";
    for (var i = 0; i < terms.length; i++) {
      var term = terms[i];
      var inTitle = t.indexOf(term) !== -1;
      var inHead = hayHead.indexOf(term) !== -1;
      if (!inTitle && !inHead) return null; // every term must match somewhere
      if (inTitle) s += 3;
      if (inHead) {
        s += 1;
        if (!matchedHeading) {
          for (var j = 0; j < hs.length; j++) {
            if (hs[j].indexOf(term) !== -1) { matchedHeading = p.headings[j]; break; }
          }
        }
      }
    }
    return { score: s, heading: matchedHeading };
  }

  function search(q) {
    q = q.trim().toLowerCase();
    if (!q) {
      return INDEX.map(function (p) { return { p: p, heading: "" }; });
    }
    var terms = q.split(/\s+/);
    var out = [];
    for (var i = 0; i < INDEX.length; i++) {
      var r = score(INDEX[i], terms);
      if (r) out.push({ p: INDEX[i], heading: r.heading, score: r.score });
    }
    out.sort(function (a, b) {
      return b.score - a.score || titleOf(a.p).localeCompare(titleOf(b.p));
    });
    return out.slice(0, MAX_RESULTS);
  }

  function render(q) {
    current = search(q);
    active = 0;
    results.innerHTML = "";
    if (current.length === 0) {
      var li = document.createElement("li");
      li.className = "sk-empty";
      li.textContent = "No matching docs";
      results.appendChild(li);
      return;
    }
    current.forEach(function (r, i) {
      var li = document.createElement("li");
      li.className = "sk-item";
      li.setAttribute("role", "option");
      li.setAttribute("aria-selected", i === active ? "true" : "false");
      li.dataset.href = r.p.page;
      var sub = r.heading ? ("§ " + r.heading) : r.p.page;
      var t = document.createElement("div"); t.className = "sk-t"; t.textContent = titleOf(r.p);
      var s = document.createElement("div"); s.className = "sk-s"; s.textContent = sub;
      li.appendChild(t); li.appendChild(s);
      li.addEventListener("mouseenter", function () { setActive(i); });
      li.addEventListener("click", function () { go(i); });
      results.appendChild(li);
    });
  }

  function setActive(i) {
    var items = results.querySelectorAll(".sk-item");
    if (!items.length) return;
    active = (i + items.length) % items.length;
    items.forEach(function (el, idx) {
      el.setAttribute("aria-selected", idx === active ? "true" : "false");
    });
    items[active].scrollIntoView({ block: "nearest" });
  }

  function go(i) {
    if (typeof i === "number") active = i;
    var r = current[active];
    if (r) window.location.href = r.p.page;
  }

  function onInputKey(e) {
    if (e.key === "ArrowDown") { e.preventDefault(); setActive(active + 1); }
    else if (e.key === "ArrowUp") { e.preventDefault(); setActive(active - 1); }
    else if (e.key === "Enter") { e.preventDefault(); go(); }
    else if (e.key === "Escape") { e.preventDefault(); close(); }
  }

  function openSearch() {
    if (open) return;
    open = true;
    lastFocused = document.activeElement;
    overlay.hidden = false;
    input.value = "";
    render("");
    input.focus();
  }

  function close() {
    if (!open) return;
    open = false;
    overlay.hidden = true;
    if (lastFocused && lastFocused.focus) lastFocused.focus();
  }

  // global ⌘K / Ctrl-K
  document.addEventListener("keydown", function (e) {
    if ((e.metaKey || e.ctrlKey) && (e.key === "k" || e.key === "K")) {
      e.preventDefault();
      open ? close() : openSearch();
    }
  });

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", build);
  } else {
    build();
  }
})();
