;; -*- lexical-binding: t; -*-
;;; minibuffer
(defvar jao-notmuch-minibuffer-string "")

(defvar jao-notmuch-minibuffer-queries
  '((:name "" :query "tag:new and not tag:draft" :face jao-themes-f00)
    (:name "B" :query "tag:new and tag:bigml and tag:inbox" :face default)
    (:name "A" :query "tag:new and tag:alba" :face default)
    (:name "b" :query "tag:new and tag:bigml and tag:bugs"
           :face jao-themes-error)
    (:name "S" :query "tag:new and tag:bigml and tag:support" :face default)
    (:name "W"
           :query "tag:new and tag:bigml and not tag:\"/support|bugs|inbox/\""
           :face default)
    (:name "I"
           :query "tag:new and tag:jao and tag:inbox"
           :face jao-themes-warning)
    (:name "J"
           :query "tag:new and tag:jao and not tag:\"/local|hacking|draft|inbox|prog|words/\""
           :face default)
    (:name "H" :query "tag:new and tag:hacking and not tag:\"/emacs/\"")
    (:name "E" :query "tag:new and tag:\"/emacs/\"")
    (:name "l" :query "tag:new and tag:local")
    (:name "F" :query "tag:new and tag:feeds and not tag:\"/emacs/\"")))

(defun jao-notmuch-notify ()
  (let ((cnts (notmuch-hello-query-counts jao-notmuch-minibuffer-queries)))
    (setq jao-notmuch-minibuffer-string
          (mapconcat (lambda (c)
                       (propertize (format "%s%s"
                                           (plist-get c :name)
                                           (plist-get c :count))
                                   'face (or (plist-get c :face)
                                             'jao-themes-dimm)))
                     cnts
                     " "))
    (jao-minibuffer-refresh)))

(when jao-notmuch-enabled
  (jao-minibuffer-add-variable 'jao-notmuch-minibuffer-string -20))

;;; saved searches
(defvar jao-notmuch--new "tag:\"/^(unread|new)$/\"")
(defvar jao-notmuch--newa (concat jao-notmuch--new " AND "))

(defun jao-notmuch--q (d0 d1 &optional k qs st)
  (let ((q (or (when qs (mapconcat #'identity qs " AND "))
               (concat jao-notmuch--newa
                       (mapconcat (lambda (d) (when d (concat "tag:" d)))
                                  (list d0 d1) " AND ")))))
    (list :name (concat d0 (when (and d1 (not (string= "" d1))) "/") d1)
          :key k :query q :search-type (or st 'tree)
          :sort-order 'oldest-first)))

(defun jao-notmuch--qn (d0 d1 k qs &optional st)
  (jao-notmuch--q d0 d1 k (cons jao-notmuch--new qs) st))

(defun jao-notmuch--sq (tag &optional k d0 d1)
  (jao-notmuch--qn (or d0 "feeds") (or d1 tag) k (list (concat "tag:" tag))))

(defun jao-notmuch-tree-widen-search ()
  (interactive)
  (when-let ((query (notmuch-tree-get-query)))
    (let ((notmuch-show-process-crypto (notmuch-tree--message-process-crypto)))
      (notmuch-tree-close-message-window)
      (notmuch-tree (string-replace jao-notmuch--newa "" query)))))

(defun jao-notmuch-widen-searches (searches &optional extra)
  (mapcar (lambda (s)
            (let* ((q (plist-get s :query))
                   (qs (string-replace jao-notmuch--newa "" q)))
              (plist-put (copy-sequence s) :query (concat qs extra))))
          searches))

(defun jao-notmuch-hello--insert-searches (searches title)
  (when-let (searches (notmuch-hello-query-counts searches))
    (let* ((cnt (when title
                  (seq-reduce (lambda (c q)
                                (+ c (or (plist-get q :count) 0)))
                              searches
                              0)))
           (title (if title (format "[ %d %s ]\n\n" cnt title) "\n"))
           (notmuch-column-control 1.0))
      (widget-insert (propertize title 'face 'jao-themes-f00))
      (notmuch-hello-insert-buttons searches))))

(defmacro jao-notmuch-def-searches (name searches)
  (declare (indent 1))
  (let ((name (and name (format "%s" name)))
        (id (intern (format "jao-notmuch-%s-searches" (or name (gensym))))))
    `(progn (defvar ,id ,searches)
            (defun ,id () (jao-notmuch-hello--insert-searches ,id ,name))
            (setq notmuch-saved-searches (append notmuch-saved-searches ,id))
            (add-to-list 'notmuch-hello-sections ',id t))))

(setq notmuch-hello-sections nil notmuch-saved-searches nil)

(jao-notmuch-def-searches bigml
  `(,(jao-notmuch--q "bigml" "inbox" "bi")
    ,(jao-notmuch--q "bigml" "alba" "ba")
    ,(jao-notmuch--q "bigml" "support" "bs")
    ,(jao-notmuch--q "bigml" "bugs" "bb")
    ,(jao-notmuch--q "bigml" "drivel" "bd")
    ,(jao-notmuch--q "bigml" "lists" "bl")))

(jao-notmuch-def-searches inbox
  `(,(jao-notmuch--q "jao" "inbox" "ji")
    ,(jao-notmuch--qn "jao" "bills" "jb" '("tag:bills"))
    ,(jao-notmuch--q "jao" "drivel" "jd")
    ,(jao-notmuch--q "jao" "mdk" "jm")
    ,(jao-notmuch--qn "jao" "hacking" "jh" '("tag:hacking" "not tag:\"/emacs/\""))
    ,(jao-notmuch--qn "jao" "local" "jl" '("tag:local"))))

(jao-notmuch-def-searches news
  (mapcar #'jao-notmuch--sq '("news" "fun" "words" "computers")))

(jao-notmuch-def-searches hacking
  (mapcar #'jao-notmuch--sq '("xmobar" "geiser" "mdk" "mailutils" "notmuch")))

(jao-notmuch-def-searches prog
  (append (mapcar #'jao-notmuch--sq
                  '( "lobsters" "clojure"  "lisp" "scheme"
                    "haskell" "idris" "erlang" "pharo"))
          `(,(jao-notmuch--qn "feeds" "prog" "fp"
                              '("tag:prog" "not tag:\"/emacs/\"")))))

(jao-notmuch-def-searches emacs
  `(,(jao-notmuch--sq "emacs" "ee" "emacs" "feeds")
    ,(jao-notmuch--sq "emacs-help" "eh" "emacs" "help")
    ,(jao-notmuch--sq "emacs-github" "eg" "emacs" "github")
    ,(jao-notmuch--sq "emacs-devel" "ed" "emacs" "devel")
    ,(jao-notmuch--sq "emacs-bugs" "eb" "emacs" "bugs")
    ,(jao-notmuch--sq "emacs-diffs" "ec" "emacs" "diffs")
    ,(jao-notmuch--sq "emacs-orgmode" "eo" "emacs" "org")))

(jao-notmuch-def-searches sci
  (mapcar #'jao-notmuch--sq
          '("philosophy" "math" "physics" "sci" "gr-qc" "quant-ph")))

(jao-notmuch-def-searches flags
  (jao-notmuch-widen-searches notmuch-saved-searches " AND tag:flagged"))

(jao-notmuch-def-searches nil
  `(,(jao-notmuch--q "bml" "flagged" "rb" '("tag:flagged" "tag:bigml"))
    ,(jao-notmuch--q "jao" "flagged" "rj" '("tag:flagged" "tag:jao"))
    ,(jao-notmuch--q "feeds" "flagged" "rf" '("tag:flagged" "tag:feeds"))))

(jao-notmuch-def-searches today
  `(,(jao-notmuch--q "new" nil "nn" '("tag:new" "not tag:draft"))
    ,(jao-notmuch--q "jao" "drafts" "d" '("tag:draft"))
    ,(jao-notmuch--q "bml" "sent" "ts"
                     '("tag:bigml" "date:1d.." "tag:sent"))
    ,(jao-notmuch--q "jao" "sent" "tS"
                     '("tag:\"/jao|hacking/\"" "date:1d.." "tag:sent"))
    ,(jao-notmuch--q "bml" "today" "tb"
                     '("not tag:sent" "tag:bigml" "date:24h.."))
    ,(jao-notmuch--q "jao" "today" "tj"
                     '("tag:jao" "date:24h.."
                       "not tag:\"/(sent|feeds|spam|local)/\""))))

(jao-notmuch-def-searches trove
  (mapcar (lambda (m) (list :query (concat "tag:trove and tag:" m)
                            :name (concat "trove/" m)
                            :key (concat "t" (substring m 0 1))
                            :search-type 'tree))
          '("jao" "hacking" "feeds" "bills")))

(jao-notmuch-def-searches nil
  '((:query "not tag:trove and not tag:bigml" :name "jao/untroved")
    (:query "tag:sent and tag:bigml" :name "bigml/sent")
    (:query "tag:sent and not tag:bigml" :name "jao/sent")
    (:query "*" :name "messages")))

(defvar jao-notmuch-widened-searches
  (jao-notmuch-widen-searches notmuch-saved-searches))

(defun jao-notmuch-jump-search (&optional widen)
  (interactive "P")
  (let ((notmuch-saved-searches
         (if widen jao-notmuch-widened-searches notmuch-saved-searches)))
    (notmuch-jump-search)))

;;; tags
(defvar jao-notmuch--shared-tags
  '("new" "unread" "flagged" "signed" "sent" "attachment" "forwarded" "inbox"
    "encrypted" "gmane" "gnus" "feeds" "rss" "mce" "trove" "prog" "emacs"))

(defun jao-notmuch--subtags (tag &rest excl)
  (let* ((cmd (concat "notmuch search --output=tags tag:" tag))
         (ts (split-string (shell-command-to-string cmd))))
    (seq-difference ts (append jao-notmuch--shared-tags (cons tag excl)))))

(setq notmuch-archive-tags '("+trove" "-new" "-drivel" "-words" "-inbox")
      notmuch-show-mark-read-tags '("-new" "-unread")
      notmuch-tag-formats
      (let (;; (d `(:foreground ,(face-attribute 'jao-themes-dimm :foreground)))
            (e `(:foreground ,(face-attribute 'jao-themes-error :foreground))))
        `(("unread")
          ("signed")
          ("new" "N")
          ("replied" "↩" (propertize tag 'face '(:family "Fira Code")))
          ("sent" "🛪")
          ("attachment" "📎")
          ("deleted" "🗙" (propertize tag 'face '(:underline nil ,@e)))
          ("flagged" "✓")
          ("jao" "j")
          ("bigml" "b")
          ("feeds" "f")
          ("gmane" "g")))
      notmuch-tag-deleted-formats
      '(("unread")
        ("new")
        ("flagged")
        ("deleted")
        (".*" (notmuch-apply-face tag 'notmuch-tag-deleted))))

(with-eval-after-load "notmuch-tag"
  (advice-add #'notmuch-read-tag-changes
              :filter-return (lambda (x) (mapcar #'string-trim x))))

;;; package
;; (add-to-list 'load-path "/usr/local/share/emacs/site-lisp/")
(jao-load-path "notmuch")

(use-package notmuch
  :init
  (setq notmuch-address-use-company t
        notmuch-address-command 'as-is
        notmuch-always-prompt-for-sender t
        notmuch-draft-folder "drafts"
        notmuch-draft-quoted-tags '("part")
        notmuch-fcc-dirs
        '(("\\(support\\|education\\)@bigml.com" . nil)
          (".*@bigml.com" . "bigml.inbox -new -unread +sent +bigml")
          (".*" . "jao.inbox -new -unread +sent +jao"))
        notmuch-maildir-use-notmuch-insert t)

  :custom ((notmuch-address-internal-completion '(sent nil)))

  :config

  (add-hook 'message-send-hook #'notmuch-mua-attachment-check)

  (when jao-notmuch-enabled
    (define-key message-mode-map (kbd "C-c C-d") #'notmuch-draft-postpone)
    (setq message-directory "~/var/mail/"
          message-auto-save-directory "/tmp"
          mail-user-agent 'message-user-agent))

  :bind (:map notmuch-common-keymap
         (("E" . jao-notmuch-open-enclosure)
          ("B" . notmuch-show-resend-message)
          ("b" . jao-notmuch-browse-urls))))

(use-package jao-notmuch :demand t)

;;; hello
;; (defun jao-notmuch-hello--header () (insert " "))
;; (when (display-graphic-p)
;;   (add-to-list 'notmuch-hello-sections 'jao-notmuch-hello--header))

(add-to-list 'notmuch-hello-sections 'notmuch-hello-insert-alltags t)

(defun jao-notmuch-refresh-agenda ()
  (interactive)
  (save-window-excursion (org-agenda-list))
  (let ((b (current-buffer)))
    (pop-to-buffer "*Calendar*")
    (goto-char (point-min))
    (calendar-goto-today)
    (pop-to-buffer b)))

(defun jao-notmuch-hello-first ()
  (interactive)
  (let ((inhibit-message t))
    (goto-char (point-min))
    (widget-forward 1)))

(defun jao-notmuch-refresh-hello (&optional agenda)
  (interactive "P")
  (ignore-errors
    (when (and (string= "mail" (jao-afio-frame-name))
               (derived-mode-p 'notmuch-hello-mode))
      (when (not (string-blank-p jao-notmuch-minibuffer-string))
        (let ((notmuch-hello-auto-refresh nil)) (notmuch-hello)))
      (when agenda (jao-notmuch-refresh-agenda))
      (unless (widget-at) (jao-notmuch-hello-first)))))

(defvar jao-notmuch-hello--sec-rx "^\\(\\[ [0-9]+\\|All tags:.+\\)")

(defun jao-notmuch-hello-next-section ()
  (interactive)
  (when (re-search-forward jao-notmuch-hello--sec-rx  nil t)
    (widget-forward 1)))

(defun jao-notmuch-hello-prev-section ()
  (interactive)
  (beginning-of-line)
  (unless (looking-at-p jao-notmuch-hello--sec-rx)
    (re-search-backward jao-notmuch-hello--sec-rx nil t))
  (when (re-search-backward jao-notmuch-hello--sec-rx  nil t)
    (end-of-line)
    (widget-forward 1)))

(defun jao-notmuch-hello-next ()
  (interactive)
  (if (widget-at)
      (widget-button-press (point))
    (jao-notmuch-hello-next-section)))

(use-package notmuch-hello
  :init
  (setq notmuch-column-control 1.0
        notmuch-hello-hide-tags nil
        notmuch-hello-thousands-separator ","
        notmuch-hello-auto-refresh t
        notmuch-show-all-tags-list nil
        notmuch-show-logo nil
        notmuch-show-empty-saved-searches nil)

  :hook ((notmuch-hello-refresh . jao-notmuch-notify))

  :config
  (when jao-notmuch-enabled
    (add-hook 'jao-afio-switch-hook #'jao-notmuch-refresh-hello))

  :bind (:map notmuch-hello-mode-map
         (("a" . jao-notmuch-refresh-agenda)
          ("g" . jao-notmuch-refresh-hello)
          ("j" . jao-notmuch-jump-search)
          ("n" . jao-notmuch-hello-next)
          ("p" . widget-backward)
          ("SPC" . widget-button-press)
          ("/" . consult-notmuch)
          ("." . jao-notmuch-hello-first)
          ("[" . jao-notmuch-hello-prev-section)
          ("]" . jao-notmuch-hello-next-section))))

;;; show
(defun jao-notmuch-open-enclosure (add)
  (interactive "P")
  (with-current-notmuch-show-message
   (goto-char (point-min))
   (if (not (search-forward "Enclosure:" nil t))
       (user-error "No enclosure in message body")
     (re-search-forward "https?://" nil t)
     (if-let (url (thing-at-point-url-at-point))
         (progn
           (message "%s %s ..." (if add "Adding" "Playing") url)
           (unless add (jao-mpc-clear))
           (jao-mpc-add-url url)
           (unless add (jao-mpc-play)))
       (error "Found an enclosure, but not a link!")))))

(defconst jao-mail-clean-rx
  (regexp-opt '("ElDiario.es - ElDiario.es: " "The Guardian: "
                "The Conversation – Articles (UK): ")))

(defun jao-mail-clean-address (args)
  (when-let ((address (car args)))
    (list (if (string-match ".+ updates on arXiv.org: \\(.+\\)" address)
              (with-temp-buffer
                (insert (match-string 1 address))
                (let ((shr-width 1000))
                  (shr-render-region (point-min) (point-max)))
                (replace-regexp-in-string "\"" "" (buffer-string)))
            (replace-regexp-in-string jao-mail-clean-rx "" address)))))

(use-package notmuch-show
  :init
  (setq gnus-blocked-images "."
        notmuch-message-headers
        '("To" "Cc" "Date" "Reply-To" "List-Id" "X-RSS-Feed")
        notmuch-show-only-matching-messages t
        notmuch-show-part-button-default-action 'notmuch-show-view-part
        notmuch-wash-signature-lines-max 0
        notmuch-wash-wrap-lines-length 120
        notmuch-wash-citation-lines-prefix 120
        notmuch-wash-citation-lines-suffix 120
        notmuch-show-text/html-blocked-images "."
        jao-notmuch-header-line-format
        (if jao-mode-line-in-minibuffer
            "%Q  [%N / %M / %T] %n / %m / %t"
          "[%N / %M / %T] %n / %m / %t")
        notmuch-show-header-line #'jao-notmuch-message-header-line)

  :config

  (advice-add 'notmuch-clean-address :filter-args #'jao-mail-clean-address)
  (add-hook 'notmuch-show-mode-hook (lambda () (setq fill-column 80)))

  :bind
  (:map notmuch-show-mode-map
   (("h" . jao-notmuch-goto-tree-buffer)
    ("TAB" . jao-notmuch-show-next-button)
    ([backtab] . jao-notmuch-show-previous-button)
    ("RET" . jao-notmuch-show-ret))))

;;; search
(use-package notmuch-search
  :init (setq notmuch-search-result-format
              '(("date" . "%12s ")
                ("count" . "%-7s ")
                ("authors" . "%-35s")
                ("subject" . " %-100s")
                (jao-notmuch-format-tags . "  (%s)"))
              notmuch-search-buffer-name-format "*%s*"
              notmuch-saved-search-buffer-name-format "*%s*")
  :bind (:map notmuch-search-mode-map
         (("RET" . notmuch-tree-from-search-thread)
          ("M-RET" . notmuch-search-show-thread))))

;;; tree
(defun jao-notmuch-tree--forward (&optional prev)
  (interactive)
  (forward-line (if prev -1 1))
  (when prev (forward-char 2))
  (jao-notmuch-tree-scroll-or-next))

(defun jao-notmuch-tree--backward ()
  (interactive)
  (jao-notmuch-tree--forward t))

(defun jao-notmuch--via-url ()
  (when (window-live-p notmuch-tree-message-window)
    (with-selected-window notmuch-tree-message-window
      (goto-char (point-min))
      (when (re-search-forward "^Via: http" nil t)
        (thing-at-point-url-at-point)))))

(defun jao-notmuch-browse-url (ext)
  (interactive "P")
  (when-let (url (or (jao-notmuch--via-url)
                     (car (last (jao-notmuch-message-urls)))))
    (funcall (if ext browse-url-secondary-browser-function #'browse-url)
             url)))

(defun jao-notmuch-adjust-tree-fonts (&optional family)
  (let ((fg (face-attribute 'jao-themes-dimm :foreground)))
    (dolist (f '(notmuch-tree-match-tree-face
                 notmuch-tree-no-match-tree-face))
      (if family
          (set-face-attribute f nil :family family :foreground fg)
        (set-face-attribute f nil :foreground fg)))))

(use-package notmuch-tree
  :init
  (setq notmuch-tree-result-format
        `(("date" . "%12s  ")
          ("authors" . "%-25s")
          ;; (jao-notmuch-format-author . 25)
          (jao-notmuch-format-msg-ticks . ,jao-mails-regexp)
          (jao-notmuch-format-tree-and-subject . "%>-85s")
          (jao-notmuch-format-tags . "  (%s)"))
        notmuch-unthreaded-result-format notmuch-search-result-format
        consult-notmuch-result-format
        `((jao-notmuch-format-msg-ticks . ,jao-mails-regexp)
          ("date" . "%12s  ")
          ("authors" . "%-35s")
          ("subject" . " %-100s")
          (jao-notmuch-format-tags . "  (%s)"))
        notmuch-tree-thread-symbols
        '((prefix . "─") (top . "─") (top-tee . "┬")
          (vertical . "│") (vertical-tee . "├") (bottom . "╰")
          (arrow . ""))
        ;; notmuch-tree-thread-symbols
        ;; '((prefix . " ") (top . " ") (top-tee . " ")
        ;;   (vertical . " ") (vertical-tee . " ") (bottom . " ")
        ;;   (arrow . ""))
        notmuch-tree-outline-enabled t
        notmuch-tree-outline-visibility 'hide-others
        notmuch-tree-outline-auto-close t
        notmuch-tree-outline-open-on-next t)
  :config

  (when (display-graphic-p)
    (jao-notmuch-adjust-tree-fonts
     (when (string-prefix-p "Hack" jao-themes-default-face) "Source Code Pro")))

  (defun jao-notmuch-before-tree (&rest _args)
    (when (string= (buffer-name) "*notmuch-hello*")
      (split-window-right 40)
      (other-window 1)))

  (defvar jao-notmuch--visits 0)

  (defun jao-notmuch-after-tree-quit (&optional _both)
    (when (and (not (derived-mode-p 'notmuch-tree-mode 'notmuch-hello-mode))
               (save-window-excursion (other-window -1)
                                      (derived-mode-p 'notmuch-hello-mode)))
      (delete-window)
      (jao-notmuch-refresh-hello (= 0 (mod (cl-incf jao-notmuch--visits) 100)))))

  (defun jao-notmuch-tree--sentinel (proc)
    (when (eq (process-status proc) 'exit)
      (let ((inhibit-read-only t))
        (save-excursion
          (goto-char (point-max))
          (when (re-search-backward "^End of search results." nil t)
            (delete-line))))))

  (add-hook 'notmuch-tree-process-exit-functions #'jao-notmuch-tree--sentinel)

  (advice-add 'notmuch-tree :before #'jao-notmuch-before-tree)
  (advice-add 'notmuch-tree-quit :after #'jao-notmuch-after-tree-quit)

  :bind (:map notmuch-tree-mode-map
              (("b" . jao-notmuch-browse-urls)
               ("d" . jao-notmuch-tree-toggle-delete)
               ("D" . jao-notmuch-tree-toggle-delete-thread)
               ("h" . jao-notmuch-goto-message-buffer)
               ("i" . jao-notmuch-toggle-images)
               ("k" . jao-notmuch-tree-read-thread)
               ("N" . jao-notmuch-tree--forward)
               ("O" . notmuch-tree-toggle-order)
               ("o" . jao-notmuch-tree-widen-search)
               ("P" . jao-notmuch-tree--backward)
               ("r" . notmuch-tree-reply)
               ("R" . notmuch-tree-reply-sender)
               ("s" . jao-notmuch-tree-toggle-spam)
               ("u" . jao-notmuch-tree-toggle-flag)
               ("v" . notmuch-tree-scroll-message-window)
               ("V" . notmuch-tree-scroll-message-window-back)
               ("x" . jao-notmuch-arXiv-capture)
               ("<" . jao-notmuch-tree-beginning-of-buffer)
               (">" . jao-notmuch-tree-end-of-buffer)
               ("\\" . notmuch-tree-view-raw-message)
               ("." . jao-notmuch-toggle-mime-parts)
               ("=" . jao-notmuch-tree-toggle-message)
               ("RET" . jao-notmuch-tree-show-or-scroll)
               ("SPC" . jao-notmuch-tree-scroll-or-next)
               ("M-g" . jao-notmuch-browse-url)
               ("M-u" . jao-notmuch-tree-reset-tags))))

;;; browse-url
(defvar jao-notmuch-url-rx "^notmuch:\\(/+\\|id:\\)\\(.+\\)")

(defun jao-notmuch-open-url (url &rest _)
  (and (string-match jao-notmuch-url-rx url)
       (notmuch-show (concat "id:" (match-string 2 url)))))

(add-to-list 'browse-url-handlers
             (cons jao-notmuch-url-rx 'jao-notmuch-open-url))

;;; org mode
(defvar jao-org-notmuch-last-subject nil)
(defun jao-org-notmuch-last-subject () jao-org-notmuch-last-subject)

(defun jao-notmuch--add-tags (tags)
  (if (derived-mode-p 'notmuch-show-mode)
      (notmuch-show-add-tag tags)
    (notmuch-tree-add-tag tags)))

(defun org-notmuch-store-link ()
  "Store a link to a notmuch mail message."
  (cl-case major-mode
    ((notmuch-show-mode notmuch-tree-mode)
     ;; Store link to the current message
     (let* ((id (notmuch-show-get-message-id))
            (link (concat "notmuch:" id))
            (subj (notmuch-show-get-subject))
            (description (format "Mail: %s" subj)))
       (setq jao-org-notmuch-last-subject subj)
       (when (y-or-n-p "Archive message? ")
         (jao-notmuch--add-tags '("+trove")))
       (when (y-or-n-p "Flag message? ")
         (jao-notmuch--add-tags '("+flagged")))
       (org-link-store-props :type "notmuch"
                             :link link
                             :description description)))
    (notmuch-search-mode
     ;; Store link to the thread on the current line
     (let* ((id (notmuch-search-find-thread-id))
            (link (concat "notmuch:" id))
            (subj (notmuch-search-find-subject))
            (description (format "Mail: %s" subj)))
       (setq jao-org-notmuch-last-subject subj)
       (org-link-store-props
        :type "notmuch"
        :link link
        :description description)))))

(with-eval-after-load "org"
  (org-link-set-parameters "notmuch"
                           :follow 'notmuch-show
                           :store 'org-notmuch-store-link))
;;; arXiv
(use-package org-capture
  :config
  (add-to-list 'org-capture-templates
               '("X" "arXiv" entry (file "notes/physics/arxiv.org")
                 "* %(jao-org-notmuch-last-subject)\n %i"
                 :immediate-finish t)
               t)
  (org-capture-upgrade-templates org-capture-templates))

(defun jao-notmuch-arXiv-capture ()
  (interactive)
  (save-window-excursion
    (jao-notmuch-goto-message-buffer)
    (save-excursion
      (goto-char (point-min))
      (re-search-forward "\\[ text/html \\]")
      (forward-paragraph)
      (setq-local transient-mark-mode 'lambda)
      (set-mark (point))
      (goto-char (point-max))
      (org-capture nil "X"))))

;;; html renderer
(when jao-notmuch-enabled (setq mm-text-html-renderer 'shr))

;;; consult
(jao-load-path "consult-notmuch")
(require 'consult-notmuch)
(consult-customize consult-notmuch :preview-key 'any)

(defvar jao-consult-notmuch-history nil)

(defvar jao-mailbox-folders '("bigml" "jao"))

(defun jao-consult-notmuch-folder (&optional tree folder)
  (interactive "P")
  (let* ((folder (if folder
                     (file-name-as-directory folder)
                   (completing-read "Group: "
                                    jao-mailbox-folders
                                    nil nil nil
                                    jao-consult-notmuch-history
                                    ".")))
         (folder (replace-regexp-in-string "/\\(.\\)" ".\\1" folder))
         (init (read-string "Initial query: "))
         (init (format "folder:/%s/ %s" folder init)))
    (if tree (consult-notmuch-tree init) (consult-notmuch init))))

(with-eval-after-load "notmuch-hello"
  (define-key notmuch-hello-mode-map "f" #'jao-consult-notmuch-folder))
;;; recoll
(defun jao-notmuch-open-file (fname &optional _page)
  (with-temp-buffer
    (insert-file-contents-literally fname)
    (goto-char (point-min))
    (and (re-search-forward "^Message-ID: <\\([^>]+\\)>$" nil t)
         (notmuch-show (concat "id:" (match-string 1))))))

(when jao-notmuch-enabled
  (with-eval-after-load "org"
    (org-link-set-parameters "message" :follow #'jao-notmuch-open-file))

  (with-eval-after-load "consult-recoll"
    (add-to-list 'consult-recoll-open-fns
                 '("message/rfc822" . jao-notmuch-open-file))))

;;; .
(provide 'jao-custom-notmuch)