// Pure, dependency-free ranking of a vocabulary against a query string.
// Used by both the CodeMirror editor (via autocomplete.js) and the
// runtime console (via the vocab-rank bundle exposed on window).
//
// Score (lower = better):
//   exact match → 0
//   prefix match → 1 + label.length      (shorter prefix matches win)
//   substring match → 10000 + indexOf    (earlier substring beats later)
//   no match → -1 (excluded)

function score(query, label) {
  if (label === query) return 0;
  if (label.startsWith(query)) return 1 + label.length;
  const i = label.indexOf(query);
  if (i !== -1) return 10000 + i;
  return -1;
}

// vocab shape: { cvars: [{name, desc?}, …], commands: [{name, desc?}, …] }
export function rankVocab(query, vocab, { limit = 50 } = {}) {
  if (!query) return [];
  const q = query.toLowerCase();

  const entries = [
    ...vocab.cvars.map(e => ({ ...e, kind: "cvar" })),
    ...vocab.commands.map(e => ({ ...e, kind: "command" })),
  ];

  const scored = [];
  for (const e of entries) {
    const s = score(q, e.name.toLowerCase());
    if (s === -1) continue;
    scored.push([s, e]);
    if (scored.length > limit * 4) break;
  }
  scored.sort((a, b) => a[0] - b[0]);
  return scored.slice(0, limit).map(([, e]) => e);
}
