;; -*- lexical-binding: t; -*-

(require 'syd/base)
(require 'syd/keymaps)
(require 'syd/org)

(defun syd-org--init-roam-keybinds ()
  (general-def
    :prefix-map 'syd-org-roam-mode-map
    "i" #'org-roam-node-insert
    "r a" #'org-roam-ref-add
    "r r" #'org-roam-ref-remove
    "a a" #'org-roam-alias-add
    "a r" #'org-roam-alias-remove)
  (general-def
    :prefix-map 'syd-leader-notes-map
    "r" `("Org-roam" . ,syd-leader-notes-roam-map))
  ;; Rebind Imenu keybind to `consult-org-heading'.  It's similar enough in
  ;; appearance and functionality, but more reliable and "correct."
  ;; REVIEW: Perhaps it would be best to implement `imenu-create-index-function'
  ;; using `consult-org-heading'?
  (general-def
    :keymaps 'org-mode-map
    [remap consult-imenu] #'consult-org-heading
    [remap imenu] #'consult-org-heading)
  (general-define-key
   :keymaps 'org-mode-map
   :states '(normal visual motion emacs insert)
   :major-modes t
   :prefix syd-localleader-key
   :non-normal-prefix syd-alt-localleader-key
   "m" `("Org-roam" . ,syd-org-roam-mode-map)))

;; Unlike those appearing in `syd-org--init-roam-keybinds', these should be
;; available even outside of Org-mode.
(general-def
  :prefix-map 'syd-leader-notes-roam-map
  "f" #'org-roam-node-find
  "d t" #'org-roam-dailies-capture-today
  "d T" #'org-roam-dailies-goto-today
  "d d" #'org-roam-dailies-goto-date)

(use-package org-roam
  :hook (org-load . syd-org-init-roam-h)
  :commands (org-roam-buffer-toggle-display
             org-roam-dailies-capture-today
             org-roam-dailies-goto-date
             org-roam-dailies-goto-today
             org-roam-dailies-goto-tomorrow
             org-roam-dailies-goto-yesterday)
  :init (progn (syd-org--init-roam-keybinds)
               (syd-load-packages-incrementally
                '(ansi-color dash f rx seq magit-section emacsql)))
  :custom ((org-roam-directory org-directory)
           (org-roam-db-location (file-name-concat syd-cache-dir
                                                   "org-roam.db"))
           ;; Make org-roam buffer sticky; i.e. don't replace it when opening a
           ;; file with an *-other-window command.
           (org-roam-buffer-window-parameters '((no-delete-other-windows . t)))
           (org-roam-completion-everywhere t)
           (org-roam-dailies-capture-templates
            `(("d" "default" entry "* %?\n%U"
               :target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>")
               :empty-lines 1)))
           (org-roam-capture-templates
            (let ((default-target-file-name
                   "%<%Y%m%d%H%M%S>-${slug}.org"))
              `(("d" "default" plain "%?"
                 :target (file+head ,default-target-file-name
                                    "#+title: ${title}")
                 :unnarrowed t)
                ("r" "recipe" plain
                 (file ,(syd-emacs-file "lisp/syd/org/roam/recipe-template.org"))
                 :target (file ,default-target-file-name))
                ("C" "class" plain
                 (file ,(syd-emacs-file "lisp/syd/org/roam/class-template.org"))
                 :target (file ,default-target-file-name))
		("K" "Today's Korean" plain
		 (file ,(syd-emacs-file "lisp/syd/org/roam/todays-korean.org"))
		 :target (file "todays-korean/%<%Y-%m-%d>.org"))
		("I" "Korean irregularity class" plain
		 (file ,(syd-emacs-file "lisp/syd/org/roam/irregularity-class.org"))
		 :target (file ,default-target-file-name)))))
	   (org-roam-link-auto-replace nil))
  :config
  (add-to-list 'org-agenda-files org-roam-directory)
  (with-eval-after-load 'org-roam-dailies
    (add-to-list 'org-agenda-files
                 (file-name-concat org-roam-directory
                                   org-roam-dailies-directory)))
  (defun syd-org-init-roam-h ()
    "Setup `org-roam' but don't immediately initialize its database.  Instead,
initialize it when it will be actually needed."
    (cl-letf (((symbol-function #'org-roam-db-sync) #'ignore))
      (org-roam-db-autosync-enable)))

  ;; (syd-org--init-roam-keybinds)

  (syd-defadvice syd-org-roam-try-init-db-a (&rest _)
    "Try to initialize org-roam database at the last possible safe moment.
In case of failure, fail gracefully."
    :before #'org-roam-db-query
    (message "Initializing org-roam database...")
    (advice-remove 'org-roam-db-query #'syd-org-roam-try-init-db-a)
    (org-roam-db-sync)))

(provide 'syd/org/roam)
