import type { LatexBibliographyPlan, LatexCompileFile } from './types';

const decoder = new TextDecoder();
const TEX_SOURCE_EXTENSIONS = /\.(?:tex|ltx|sty|cls)$/i;

function projectSource(files: readonly LatexCompileFile[]): string {
  return files
    .filter((file) => TEX_SOURCE_EXTENSIONS.test(file.path))
    .map((file) => decoder.decode(file.content))
    .join('\n');
}

/** Decides which browser compiler driver stages should run for this project. */
export function planBibliographyPasses(
  files: readonly LatexCompileFile[],
): LatexBibliographyPlan {
  const source = projectSource(files);
  const hasBibFile = files.some((file) => /\.bib$/i.test(file.path));
  const classicBib = /\\bibliography\s*\{|\\bibliographystyle\s*\{/m.test(source);
  const biblatex = /\\addbibresource(?:\[[^\]]*\])?\s*\{/m.test(source);
  const explicitBibtex = /\\usepackage\s*\[[^\]]*backend\s*=\s*bibtex[^\]]*\]\s*\{biblatex\}/mi.test(
    source,
  );
  const citations = /\\(?:cite|parencite|textcite|autocite|footcite)\*?(?:\[[^\]]*\]){0,2}\s*\{/m.test(
    source,
  );
  const makeindex = /\\makeindex\b|\\printindex\b/m.test(source);
  const biberRequested = biblatex && !explicitBibtex;

  return {
    bibtex:
      hasBibFile &&
      !biberRequested &&
      (classicBib ||
        (!biblatex && citations) ||
        (biblatex && explicitBibtex)),
    // BibLaTeX defaults to Biber unless the document explicitly selects
    // backend=bibtex. Treat the default honestly rather than silently running
    // BibTeX and producing an apparently successful but incomplete document.
    biberRequested,
    makeindex,
    rerun: true,
  };
}
