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

;;; browse-url and afio
(defun jao-w3m-find-url (url)
  (let* ((url (w3m-canonicalize-url url))
         (fn `(lambda (b)
                (with-current-buffer b
                  (string= ,url (w3m-canonicalize-url w3m-current-url))))))
    (when-let* ((b (seq-find fn (w3m-list-buffers))))
      (pop-to-buffer b))))

(defun jao-w3m-browse-url (url &rest r)
  (jao-afio-goto-www)
  (select-window (frame-first-window))
  (unless (jao-w3m-find-url url)
    (w3m-goto-url-new-session url)))

(defun jao-w3m-download (arg)
  (interactive "P")
  (jao-download (w3m-anchor) arg))

(setq jao-afio-use-w3m t)
(setq jao-browse-url-function 'jao-w3m-browse-url)

;;; multipart html renderer
(defun jao-w3m-html-renderer (handle)
  (let ((w3m-message-silent t)
        (w3m-fill-column 120)
        (mm-w3m-safe-url-regexp nil)
        (mm-inline-text-html-with-w3m-keymap t))
    (condition-case e
        (mm-inline-text-html-render-with-w3m handle)
      (error (message "Error rendering page with w3m: %s" e)
             (delete-region (point) (point-max))
             (let ((shr-use-fonts nil))
               (mm-shr handle))))))

(setq mm-text-html-renderer 'jao-w3m-html-renderer)

;;; notmuch integration
(defvar-local jao-notmuch--showing-images nil)

(defun jao-notmuch--setup-w3m-images (&optional activate)
  (setq-local w3m-ignored-image-url-regexp
              (unless jao-notmuch--showing-images
                notmuch-show-text/html-blocked-images))
  (when activate
    (setq-local scroll-margin 0)
    (w3m-toggle-inline-images (if jao-notmuch--showing-images t 'turnoff))))

(defun jao-notmuch--w3m-toggle-images ()
  (save-window-excursion
    (when (or (derived-mode-p 'notmuch-show-mode)
              (jao-notmuch-goto-message-buffer nil t))
      (goto-char (point-min))
      (when (re-search-forward "^\\[ text/html " nil t)
        (when (looking-at-p "(hidden)")
          (notmuch-show-toggle-part-invisibility))
        (forward-line 1)
        (setq jao-notmuch--showing-images (not jao-notmuch--showing-images))
        (jao-notmuch--setup-w3m-images t)))))

(add-hook 'notmuch-show-mode-hook #'jao-notmuch--setup-w3m-images)

;;; org integration
(defun jao-w3m-get-link ()
  (let ((wb (w3m-alive-p)))
    (when wb
      (let ((url (with-current-buffer wb w3m-current-url))
            (title (w3m-buffer-title wb)))
        (cons url title)))))

(defun jao-insert-w3m-link ()
  (interactive)
  (let ((link (jao-w3m-get-link)))
    (when link (insert "[[" (car link) "][" (cdr link) "]]"))))

(with-eval-after-load "org"
  (require 'ol-w3m nil t)
  (define-key org-mode-map "\C-cW" 'jao-insert-w3m-link))

;;; capture page
(defun jao-w3m-capture-page ()
  (interactive)
  (let* ((title (w3m-current-title))
         (url w3m-current-url)
         (html (y-or-n-p "Save as HTML (y) or PS (n)? "))
         (basename (concat (read-string "File name: ")
                           (if html ".html" ".ps")))
         (name (expand-file-name basename jao-sink-dir)))
    (if html
        (progn
          (w3m-view-source)
          (write-region (point-min) (point-max) name nil nil nil t)
          (w3m-view-source))
      (progn
        (split-window-horizontally 85)
        (w3m-redisplay-this-page)
        (ps-print-buffer name)
        (delete-other-windows)
        (w3m-redisplay-this-page)))
    (kill-new (format "[[doc:%s][%s]] ([[%s][original]])"
                      basename title url))))

;;; consult narrowing
(with-eval-after-load "w3m-util"
  (with-eval-after-load "consult"
    (defvar jao-consult-w3m-buffer-history nil)
    (defun jao-www--item (b)
      (with-current-buffer b
        (propertize (or w3m-current-title (buffer-name))
                    'buffer b
                    'url (or w3m-current-url (buffer-name)))))
    (defvar jao-consult-w3m-source
      (list :name "www buffer"
            :category 'www-buffer
            :hidden t
            :narrow (cons ?w "www")
            :annotate (lambda (b) (when b (get-text-property 0 'url b)))
            :history 'jao-consult-w3m-buffer-history
            :items (lambda ()
                     (seq-map #'jao-www--item
                              (seq-filter #'jao-www--buffer-p (buffer-list))))
            :action (lambda (b)
                      (jao-afio-goto-www)
                      (switch-to-buffer (get-text-property 0 'buffer b)))))
    (jao-consult-add-buffer-source 'jao-consult-w3m-source)))

;;; package
(use-package w3m
  :ensure t
  :demand t
  :custom ((w3m-key-binding 'info)
           (w3m-display-mode 'dual-pane))
  :init
  (setq w3m-add-user-agent nil
        w3m-confirm-leaving-secure-page nil
        w3m-cookie-accept-bad-cookies t
        w3m-cookie-accept-domains '(".github.com"
                                    ".librarything.com"
                                    ".goodreads.com"
                                    ".sr.ht"
                                    ".gnu.org"
                                    ".codeberg.org"
                                    "codeberg.org"
                                    ".bookshop.org"
                                    ".reddit.com")
        w3m-cookie-reject-domains '(".")
        w3m-default-display-inline-images nil
        w3m-default-save-directory "~/doc/sink"
        w3m-do-cleanup-temp-files nil
        w3m-external-view-temp-directory "/tmp"
        w3m-fill-column 110
        w3m-goto-article-function 'jao-w3m-browse-url
        w3m-form-input-textarea-buffer-lines 40
        w3m-history-minimize-in-new-session t
        w3m-history-reuse-history-elements nil
        w3m-init-file nil
        w3m-image-no-idle-timer t
        w3m-make-new-session t
        w3m-profile-directory "~/.w3m"
        w3m-redisplay-pages-automatically-p nil
        w3m-resize-images t
        w3m-safe-url-regexp nil
        w3m-search-default-engine "duckduckgo" ; "google-en"
        w3m-select-buffer-horizontal-window nil
        w3m-select-buffer-window-ratio '(20 . 40)
        w3m-session-load-last-sessions t
        w3m-session-load-crashed-sessions 'ask
        w3m-show-graphic-icons-in-header-line nil
        w3m-show-graphic-icons-in-mode-line nil
        w3m-toggle-inline-images-permanently nil
        w3m-use-tab nil
        w3m-use-tab-line nil
        w3m-use-title-buffer-name t
        w3m-use-cookies t
        w3m-use-filter nil
        w3m-use-favicon nil
        w3m-use-header-line nil
        w3m-use-refresh nil
        w3m-use-symbol t)

  :config
  :bind (:map w3m-mode-map
              (("+" . w3m-zoom-in-image)
               ("-" . w3m-zoom-out-image)
               ("C-c C-@" . tracking-next-buffer)
               ("C-c C-SPC" . tracking-next-buffer)
               ("C-c C-b" . nil)
               ("C-l" . nil)
               ("C-c c" . jao-w3m-capture-page)
               ("b" . w3m-view-previous-page)
               ("B" . w3m-view-next-page)
               ("c" . w3m-print-this-url)
               ("d" . jao-w3m-download)
               ("D" . w3m-download)
               ("f" . w3m-lnum-follow)
               ("v" . jao-view-video)
               ("q" . w3m-delete-buffer)
               ("w" . org-w3m-copy-for-org-mode)
               ("x" . jao-r2e-subscribe)
               ("y" . w3m-print-current-url))))

;;; textsec
;; the way in which w3m constructs ALT text for links to images confuses
;; makes it suspicious under textsec link check.
(with-eval-after-load "textsec"
  (advice-add 'textsec-link-suspicious-p :override #'ignore))

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