;;; tools/pass/autoload.el -*- lexical-binding: t; -*-

(defun +pass--open-url (entry)
  (if-let* ((url (+pass-get-field entry +pass-url-fields)))
      (and (or (string-match-p "https?://" url)
               (error "Field for %s doesn't look like an url" item))
           (browse-url url))
    (error "url not found.")))

(defun +pass--copy (entry field text)
  (password-store-clear)
  (message "Copied %s's %s field to clipboard. Will clear in %s seconds"
           entry field (password-store-timeout))
  (kill-new text)
  (setq password-store-timeout-timer
        (run-at-time (password-store-timeout) nil 'password-store-clear)))

(defun +pass--copy-username (entry)
  (if-let* ((user (+pass-get-field entry +pass-user-fields)))
      (progn (password-store-clear)
             (message "Copied username to the kill ring.")
             (kill-new user))
    (error "Username not found.")))

(defun +pass--completing-read-field (entry)
  (let* ((data (+pass-get-entry entry))
         (field (if data (completing-read "Field: " (mapcar #'car data) nil t))))
    (+pass-get-field data field)))


;;
;; API

;;;###autoload (autoload 'auth-source-pass-parse-entry "auth-source-pass")
;;;###autoload
(defalias '+pass-get-entry #'auth-source-pass-parse-entry)

;;;###autoload
(defun +pass-get-field (entry fields &optional noerror)
  "Fetches the value of a field. FIELDS can be a list of string field names or a
single one. If a list, the first field found will be returned. Will error out
otherwise, unless NOERROR is non-nill."
  (if-let* ((data (if (listp entry) entry (+pass-get-entry entry))))
      (cl-loop for key in (doom-enlist fields)
               when (assoc key data)
               return (cdr it))
    (unless noerror
      (error "Couldn't find entry: %s" entry))))

;;;###autoload
(defun +pass-get-user (entry)
  "Fetches the user field from ENTRY. Each of `+pass-user-fields' are tried in
search of your username. May prompt for your gpg passphrase."
  (+pass-get-field entry +pass-user-fields))

;;;###autoload
(defun +pass-get-secret (entry)
  "Fetches your secret from ENTRY. May prompt for your gpg passphrase."
  (+pass-get-field entry 'secret))


;;
;; Commands

;;;###autoload (autoload 'password-store-dir "password-store")
;;;###autoload (autoload 'password-store-list "password-store")
;;;###autoload (autoload 'password-store--completing-read "password-store")

;;;###autoload
(defun +pass/edit-entry (entry)
  "Interactively search for and open a pass entry for editing."
  (interactive
   (list (password-store--completing-read)))
  (find-file (concat (expand-file-name entry (password-store-dir)) ".gpg")))

;;;###autoload
(defun +pass/copy-field (entry)
  "Interactively search for an entry and copy a particular field to your
clipboard."
  (interactive
   (list (password-store--completing-read)))
  (let* ((data (+pass-get-entry entry))
         (field (if data (completing-read "Field: " (mapcar #'car data) nil t))))
    (+pass--copy entry field (+pass-get-field data field))))

;;;###autoload
(defun +pass/copy-secret (entry)
  "Interactively search for an entry and copy its secret/password to your
clipboard."
  (interactive
   (list (password-store--completing-read)))
  (+pass--copy entry 'secret (+pass-get-secret entry)))

;;;###autoload
(defun +pass/copy-user (entry)
  "Interactively search for an entry and copy the login to your clipboard. The
fields in `+pass-user-fields' is used to find the login field."
  (interactive
   (list (password-store--completing-read)))
  (+pass--copy-username entry))

;;;###autoload
(defun +pass/browse-url (entry)
  "Interactively search for an entry and open its url in your browser. The
fields in `+pass-url-fields' is used to find the url field."
  (interactive
   (list (password-store--completing-read)))
  (+pass--open-url entry))


;;
;; Ivy interface

;;;###autoload
(defun +pass/ivy (arg)
  "TODO"
  (interactive "P")
  (ivy-read "Pass: " (password-store-list)
            :action (if arg
                        #'password-store-url
                      #'password-store-copy)
            :caller '+pass/ivy))

(after! ivy
  (ivy-add-actions
   '+pass/ivy
   '(("o" password-store-copy "copy password")
     ("e" +pass/edit-entry "edit entry")
     ("u" +pass/copy-user "copy username")
     ("b" +pass/copy-url "open url in browser")
     ("f" +pass/copy-field "get field"))))


;;
;; TODO Helm interface

;; (defun +pass/helm ()
;;   (interactive)
;;   )