import { autocompletion } from "@codemirror/autocomplete";

const WORD_RE = /[A-Za-z0-9_]{2,}/;

function rank(query, label) {
  const q = query.toLowerCase();
  const l = label.toLowerCase();
  if (l === q) return 0;
  if (l.startsWith(q)) return 1 + l.length;       // shorter prefix matches first
  const i = l.indexOf(q);
  if (i !== -1) return 10000 + i;                 // substring matches after all prefix matches
  return -1;
}

export function vocabCompletions(vocab) {
  // vocab: { cvars: [{name, desc?}, …], commands: [{name, desc?}, …] }
  const entries = [
    ...vocab.cvars.map(e => ({ ...e, kind: "cvar" })),
    ...vocab.commands.map(e => ({ ...e, kind: "command" })),
  ];

  return (context) => {
    const word = context.matchBefore(WORD_RE);
    if (!word || (word.from === word.to && !context.explicit)) return null;
    const q = word.text;

    const scored = [];
    for (const e of entries) {
      const r = rank(q, e.name);
      if (r === -1) continue;
      scored.push([r, e]);
      if (scored.length > 200) break;             // bound work; we cap to 50 below
    }
    scored.sort((a, b) => a[0] - b[0]);
    const options = scored.slice(0, 50).map(([, e]) => ({
      label: e.name,
      info: e.desc || e.kind,
      type: e.kind === "command" ? "function" : "variable",
    }));
    return { from: word.from, options, validFor: WORD_RE };
  };
}

export function autocompleteExtension(vocab) {
  return autocompletion({
    override: [vocabCompletions(vocab)],
    activateOnTyping: true,
    maxRenderedOptions: 8,
  });
}
