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

;;; Deps
(require 'jao-url)

;;; variables
(defvar jao-browse-url-function nil)
(defvar jao-browse-url-external-function nil)

;;; url around point

(defun jao--url-prompt (&optional prefix)
  (let* ((def (jao-url-around-point t))
         (prompt (concat prefix "URL" (if def (format " (%s): " def) ": "))))
    (read-string prompt nil nil def)))

;;; downloads using wget
(defun jao-wget--get-title (filename)
  (or (and (derived-mode-p 'w3m-mode) (w3m-current-title))
      (plist-get eww-data :title)
      (and (not (string-blank-p (or filename "")))
           (subst-char-in-string ?- ?
                                 (capitalize (file-name-base filename))))))

(defun jao-wget (url &optional user pwd)
  "Download URL using wget and kill a link for an org note."
  (let* ((def (file-name-nondirectory url))
         (pmt (format "Save %s to: " url))
         (read-file-name-function nil)
         (dest (expand-file-name
                (read-file-name pmt jao-sink-dir nil nil def)))
         (title (jao-wget--get-title dest))
         (src-url (or (jao-url-around-point t) (file-name-directory url)))
         (auth (when (and user pwd)
                 `(,(format "--http-user=%s" user)
                   ,(format "--http-password=%s" pwd))))
         (lnk (concat "doc:" (file-name-nondirectory dest))))
    (switch-to-buffer-other-window (get-buffer-create "*downloads*"))
    (erase-buffer)
    (kill-new (format "%s (from %s)"
                      (org-link-make-string lnk title)
                      (org-link-make-string src-url "here")))
    (apply 'make-term `("downloads" "wget" nil ,@auth "-O" ,dest ,url))))

(defun jao-download (url &optional pws)
  "Download URL using wget"
  (interactive (list (jao--url-prompt)))
  (when url
    (let ((usr (and pws (read-string "Login name: ")))
          (pwd (and pws (read-passwd "Password: "))))
      (jao-wget url usr pwd))))

(with-eval-after-load "embark"
  (define-key embark-url-map (kbd "d") #'jao-download))

;;; video
(defvar jao-video--url-rx
  (format "^https?://\\(?:www\\.\\)?%s/.+"
          (regexp-opt '("youtu.be"
                        "youtube.com"
                        "blip.tv"
                        "vimeo.com"
                        "infoq.com")
                      t)))

(defvar jao-video--ext-rx
  (format "^https?://.+/.+\\.%s" (regexp-opt '("mp3" "webm" "mp4"))))

(defun jao-video--url-p (url)
  (or (string-match-p jao-video--url-rx url)
      (string-match-p jao-video--ext-rx url)))

(defun jao--remote-run (url prg)
  (let ((args (format "%s %s" prg (shell-quote-argument url))))
    (start-process-shell-command prg nil args)))

(defun jao--mpv (url &rest _args) (jao--remote-run url "mpv"))
(defun jao--vlc (url &rest _args) (jao--remote-run url "vlc"))

(defvar jao--video-player 'jao--mpv)

(defun jao-view-video (url)
  "Tries to stream a video from the current or given URL"
  (interactive (list (jao--url-prompt "Video ")))
  (when url (funcall jao--video-player url)))

(defun jao-maybe-view-video (url &rest _ignored)
  (interactive)
  (let ((w (read-char "View video (v) or web page (w)? ")))
    (cond ((eq w ?v) (jao-view-video url))
          ((eq w ?w) (funcall jao-browse-url-external-function url))
          (t (message "Aborted")))))

;;; web browsers
(defun jao-www--buffer-p (b)
  (with-current-buffer b
    (or (derived-mode-p 'w3m-mode 'eww-mode)
        (and (boundp 'exwm-class-name)
             (member exwm-class-name '("vlc" "mpv"))))))

;;; browse-url
(require 'browse-url)

(setq browse-url-generic-program (jao-d-l "open" "firefox"))

(defun jao-browse-with-external-browser (&rest url)
  "Browse with external hogging"
  (interactive "s")
  (let ((url (or (car url) (jao-url-around-point))))
    (if (not url)
        (message "No URL at point")
      (cond ((and (jao-exwm-enabled-p) (fboundp 'jao-exwm-firefox))
             (jao-exwm-firefox))
            (jao-river-enabled (jao-river-to-ws 2))
            (jao-sway-enabled (jao-sway-firefox)))
      (browse-url-generic url))))

(setq jao-browse-url-external-function 'jao-browse-with-external-browser)

(defun jao--fln (url)
  (shell-quote-argument
   (if (string-match "^[^:]*:/*?\\(/?[^/].*\\)" url)
       (match-string-no-properties 1 url)
     url)))

(defun jao--browse-doc (url &rest _ignored)
  (let* ((url (substring-no-properties url))
         (file (jao--fln url)))
    (when file
      (unless (file-exists-p file)
        (error "File %s does not exist" file))
      (jao-open-doc file))))

(defun jao--make-file-rx (exts)
  (format "file:/?/?.+\\.%s$" (regexp-opt exts)))

(defvar jao--see-exts (jao--make-file-rx '("jpg" "jpeg" "png")))

(defvar jao--doc-exts
  (jao--make-file-rx '("ps" "ps.gz" "pdf" "dvi" "djvu" "chm")))

(defvar jao-browse-url-wget-exts
  '("ps" "pdf" "dvi" "djvu" "zip" "gz" "tgz"))

(defvar jao-browse-external-domains
  '("github.com" "gitlab.com" "slack.com" "spotify.com" "drive.google.com"
    "meet.google.com" "docs.google.com" "x.com" "twitter.com"
    "t.com" "linkedin.com" "bigml.com" "slack.com" "zoom.us"))

(defvar jao-browse--external-regexp nil)

(defun jao-browse-add-external (&rest rx)
  (dolist (r rx) (add-to-list 'jao-browse-external-domains r))
  (setq jao-browse--external-regexp
        (format "https?://\\(.+\\.\\)*%s\\(/.*\\)?"
                (regexp-opt jao-browse-external-domains)))
  (jao-browse-setup))

(defun jao-wget--regexp ()
  (concat "^http[s]?://.+\\(\\."
          (mapconcat 'identity jao-browse-url-wget-exts "\\|\\.")
          "\\)\\'"))

(defun jao--see (url &rest _r)
  (start-process-shell-command "see" nil (format "see %s" (jao--fln url))))

(defun jao--find-file-other-window (url &rest _)
  (find-file-other-window (jao--fln url)))

(defvar jao-browse--sound-rx
  (format "^https?://.*/.*\\.%s" (regexp-opt '("mp3" "flv"))))

(defun jao-browse-play-sound-url (url &rest _)
  (jao-mpc-add-or-play-url url))

(defun jao-browse-url-browse (&rest args)
  (apply jao-browse-url-function args))

(defun jao-browse-setup ()
  (jao-d-l
   (setq browse-url-handlers
         `((jao-video--url-p . jao-maybe-view-video)
           (,jao--doc-exts . jao-mac-open)
           (,jao--see-exts . jao-mac-open)
           ("^file://?.+\\.html?$" . ,jao-browse-url-function)
           ("^file://?" . jao--find-file-other-window)
           (,jao-browse--external-regexp . ,jao-browse-url-external-function)
           (,jao-browse--sound-rx . jao-browse-play-sound-url)
           ("." . jao-browse-url-browse)))
   (setq browse-url-handlers
         `((jao-video--url-p . jao-maybe-view-video)
           (,jao--doc-exts . jao--browse-doc)
           (,jao--see-exts . jao--see)
           ("^file://?.+\\.html?$" . ,jao-browse-url-function)
           ("^file://?" . jao--find-file-other-window)
           (,jao-browse--external-regexp . ,jao-browse-url-external-function)
           ("^https?://.*\\.gotomeeting\\.com\\.*" . browse-url-chrome)
           (,jao-browse--sound-rx . jao-browse-play-sound-url)
           (,(jao-wget--regexp) . jao-download)
           ("." . jao-browse-url-browse)))))

(jao-browse-add-external)

(provide 'jao-custom-browse)

;;; jao-custom-browse.el ends here
