;; Insert a bibliography into a Markdown file.
;;
;; This version does _not_ use the built-in support for citations
;; (RMarkdown-style), but instead illustrates how one would grub about
;; in the parse-tree and support citations formatted as `[[ref]]()`
;; (not a very sensible choice of syntax, but chosen as one
;; which the Markdown parser here doesn't recognise as special).
;;
;; Usage:
;;
;;     beastie make-bib.scm foo.md bibfile.bib
;;
;; The citations are indicated by links [[ref]]().
;;
;; This works with beastie v0.14.  The functions it uses may change
;; with later versions.
;;
;; Limitations:
;;
;;   * It currently support only a subset of types explicitly.
;;   * There's no discrimination between colliding author-year pairs
;;     (ie, no 1905a/b/c)
;;   * No distinction between (the equivalents of) \cite, \citep, \citeyear
;;
;; Respects BIBINPUTS.
;;
;; This file is part of Beastie <https://purl.org/nxg/dist/beastie>
;; SPDX-FileCopyrightText: 2023 Norman Gray <https://nxg.me.uk>
;; SPDX-License-Identifier: BSD-2-Clause

(module 'markdown 'xexpr 'bibtex)

(unless (= (length *command-line*) 3)
  (eprintf "Insert a bibliography into a Markdown file.~%The citations are identified by [[ref]]().~%~%")
  (eprintf "Usage:~%    beastie ~a foo.md database.bib~%" (car *command-line*))
  (eprintf "~%Respects the value of $BIBINPUTS~%")
  (exit 1))

(define *input-markdown* (cadr *command-line*))
(define *bibtex-database*
  ;; resolve-file throws an error if it can't find a file
  (resolve-file (caddr *command-line*) ".bib"))

(module "plain.scm")

;; Given a xexpr TREE with the document content (parsed from Markdown),
;; and a hash REFS (symbol? -> string?) which maps citation keys to reference text,
;; produces a copy of the input tree with (a ((href "")) "ref") elements
;; filled in.
(define (insert-refs tree refs)
  (define (edit-tree el)
    (if (list? el)
        (receive (gi atts content)
            (xexpr-disassemble el)
          (if (and (eqv? gi 'a)
                   (equal? (assv 'href atts) '(href "")))
              ;; content is ("[" ref "]")
              (let* ((key (string->symbol (cadr content)))
                     (citation (refs key)))
                (if citation
                    `(a ((href ,(sprintf "#~a" key)))
                        "(" ,citation ")")
                    `(a ((href ,(sprintf "#~a" key)))
                        "[" key "]")))
              `(,gi ,atts . ,(map edit-tree content))))
        el))
  (edit-tree tree))

;; The text contains references formatted as [[ref]](), which appear
;; in the parse-tree as (a ((href "")) "[" ref "]")
(define text
  (parse-markdown-file *input-markdown*))
(define refs
  (map (lambda (e)               ; argument is (a ((...)) "[" ref "]")
         (list-ref e 3))
       (xexpr-path-search (list 'a
                                (lambda (e)
                                  (string=? (xexpr-get-attribute e 'href) "")))
                          text)))

;; look at what we've got so far
;(eprintf "text=~s~%refs=~s~%" text refs)

(let ((bib     ;produces a list of citation? objects -- see bibtex.scm
       (assemble-bibliography
        (map string->symbol refs)
        (list *bibtex-database*))))
  (xexpr-write/xhtml!
   `(body
     ,@(cdr (insert-refs text
                         (apply hash-table
                                (apply append
                                       (map (lambda (b)
                                              (list (citation-key b) (citation-reference b)))
                                            bib)))))
     (h2 "Bibliography")
     ,@(map citation-html bib))))

;; (printf "refs=~s  bib=~s~%" refs (list (resolve-file "science" ".bib")))
;; (process-citations (map string->symbol refs)
;;                    (list (resolve-file "science" ".bib"))
;;                    #f)

;(call-with-aux-file "herbert-ives.aux" process-citations)
