(in-package #:nyxt-user) ; While implicit, this allows SLY to know which package we are in.

#+nyxt-3 (reset-asdf-registries)

(defvar *web-buffer-modes*
  '(:blocker-mode :force-https-mode
    :reduce-tracking-mode
    :user-script-mode :bookmarklets-mode)
  "The modes to enable in any web-buffer by default.
Extension files (like dark-reader.lisp) are to append to this list.

Why the variable? Because it's too much hassle copying it everywhere.")

;; Create a function to launch mpv with given url
(defun mpv (url)
  "MPV launches with given url using the fast profile."
  (uiop:launch-program (list "mpv" "--profile=fast" url "&")))

;; Create a function to download videos with youtube-dl in alacritty
(defun youtube-dl (url)
  "Download videos and audio with youtube-dl in alacritty for feedback"
  (uiop:launch-program
   (list "dlvideo" url)))


(define-configuration :web-buffer
  ((default-modes (append (list :vi-normal-mode) %slot-value%))))

(define-configuration (:modable-buffer :prompt-buffer :editor-buffer)
    "Set up Emacs keybindings everywhere possible.

If you're the VI person, then use this:
(define-configuration :web-buffer
  ((default-modes (append (list :vi-normal-mode) %slot-value%))))

You probably want to stay with CUA in :prompt-buffer, because it's too
weird using it with VI bindings. But if you're feeling risky, then:
(define-configuration :prompt-buffer
  ((default-modes (append (list :vi-insert-mode) %slot-value%))))"
  ((default-modes `(:vi-insert-mode ,@%slot-value%))))

(define-configuration :prompt-buffer
  "Make the attribute widths adjust to the content in them.

It's not exactly necessary on master, because there are more or less
intuitive default widths, but these are sometimes inefficient (and
note that I made this feature so I want to have it :P)."
  ((dynamic-attribute-width-p t)))

(define-configuration :prompt-buffer
  ((hide-single-source-header-p
    t
    :doc "This is to hide the header is there's only one source.
There also used to be other settings to make prompt-buffer a bit
more minimalist, but those are internal APIs :(")))

(define-configuration :web-buffer
  "Basic modes setup for web-buffer."
  ((default-modes `(,@*web-buffer-modes* ,@%slot-value%))))

(define-configuration :browser
  "Set new buffer URL (a.k.a. start page, new tab page)."
  ((default-new-buffer-url (quri:uri "nyxt:nyxt/mode/repl:repl"))))

(define-configuration :nosave-buffer
  "Enable proxy in nosave (private, incognito) buffers."
  ((default-modes `(:proxy-mode ,@*web-buffer-modes* ,@%slot-value%))))

(define-configuration :hint-mode
  "Set up QWERTY home row as the hint keys."
  ((hints-alphabet "DSJKHLFAGNMXCWEIO")))


(defmethod ffi-buffer-make :after ((buffer nyxt/renderer/gtk::gtk-buffer))
  "Setting WebKit-specific settings.
WARNING: Not exactly the best way to configure Nyxt, because it relies
on internal APIs and CFFI...

See
https://webkitgtk.org/reference/webkit2gtk/stable/WebKitSettings.html
for the full list of settings you can tweak this way."
  (when (slot-boundp buffer 'nyxt/renderer/gtk::gtk-object)
    (let* ((settings (webkit:webkit-web-view-get-settings
                      (nyxt/renderer/gtk::gtk-object buffer))))
      (setf
       ;; Resizeable textareas. It's not perfect, but still a cool feature to have.
       (webkit:webkit-settings-enable-resizable-text-areas settings) t
       ;; Write console errors/warnings to the shell, to ease debugging.
       (webkit:webkit-settings-enable-write-console-messages-to-stdout settings) t
       ;; "Inspect element" context menu option available at any moment.
       (webkit:webkit-settings-enable-developer-extras settings) t
       ;; Enable WebRTC.
       (webkit:webkit-settings-enable-media-stream settings) t
       ;; Use Cantarell-18 as the default font.
       (webkit:webkit-settings-default-font-family settings) "VictorMono Nerd Font"
       (webkit:webkit-settings-default-font-size settings) 16
       ;; Use Hack-17 as the monospace font.
       (webkit:webkit-settings-monospace-font-family settings) "VictorMono Nerd Font"
       (webkit:webkit-settings-default-monospace-font-size settings) 14
       ;; Use Unifont for pictograms.
       (webkit:webkit-settings-pictograph-font-family settings) "Unifont")))
  ;; Set the view background to black.
  (cffi:foreign-funcall
   "webkit_web_view_set_background_color"
   :pointer (g:pointer (nyxt/renderer/gtk:gtk-object buffer))
   ;; GdkRgba is simply an array of four doubles.
   :pointer (cffi:foreign-alloc
             :double
             :count 4
             ;; red green blue alpha
             :initial-contents '(0d0 0d0 0d0 1d0))))

;; (defmethod customize-instance ((input-buffer input-buffer) &key)
;;   (disable-modes* 'nyxt/mode/emacs:emacs-mode input-buffer)
;;   (enable-modes* 'nyxt/mode/vi:vi-normal-mode input-buffer))

;; (define-configuration browser
;;     ((external-editor-program '("emacsclient -c"))))

;; Let's create a function to hint videos, convert the url to a sting, and play them in MPV
(define-command hint-mpv nil
                "Show a set of element hints, and copy the URL of the user inputted one."
                (nyxt/mode/hint:query-hints "Copy element URL"
                                           (lambda (nyxt/mode/hint::results)
                                             ;; this converts the url to a string to be used in mpv
                                             (let*
                                                 ((url
                                                   (format nil "~a"
                                                           (url (first nyxt/mode/hint::results)))))
                                               ;; here we take that string and pipe it into mpv
                                               (mpv url)))))

;; Let's create a function to hint videos, convert the url to a sting, and download with ytdl
(define-command hint-ytdl nil
                "Show a set of element hints, and copy the URL of the user inputted one."
                (nyxt/mode/hint:query-hints "Copy element URL"
                                           (lambda (nyxt/mode/hint::results)
                                             ;; this converts the url to a string to be used in yt-dlp
                                             (let*
                                                 ((url
                                                   (format nil "~a"
                                                           (url (first nyxt/mode/hint::results)))))
                                               ;; here we take that string and pipe it into yt-dlp
                                               (youtube-dl url)))))

(define-configuration :web-buffer
  "set better scroll distance"
  ((scroll-distance 350)))

(define-configuration :document-mode
  "Add basic keybindings."
  ((keyscheme-map
    (keymaps:define-keyscheme-map
        "custom" (list :import %slot-value%)
      ;; If you want to have VI bindings overriden, just use
      ;; `scheme:vi-normal' or `scheme:vi-insert' instead of
      ;; `scheme:emacs'.
      nyxt/keyscheme:vi-normal
      (list "K" 'switch-buffer-next
            "J" 'switch-buffer-previous
            "b" 'switch-buffer
            "d" 'delete-current-buffer
            "D" 'delete-buffer
            "r" 'reload-current-buffer
            "R" 'reload-buffers
            "v" 'hint-mpv
            "V" 'hint-ytdl
            "L" 'history-forwards
            "H" 'history-backwards
            "gv" :visual-mode
            "C-i" :input-edit-mode)))))

(defvar *my-search-engines*
  (list
   '("google" "https://google.com/search?q=~a" "https://google.com")
   '("searx" "https://search.tfcconnection.org/search?q=~a" "https://search.tfcconnection.org/"))
  "List of search engines.")

(define-configuration context-buffer
  "Go through the search engines above and make-search-engine out of them."
  ((search-engines
    (append
     (mapcar (lambda (engine) (apply 'make-search-engine engine))
             *my-search-engines*)
     %slot-default%))))

(define-nyxt-user-system-and-load "nyxt-user/search-engines"
  :depends-on (:nx-search-engines) :components ("search-engines.lisp"))

(define-nyxt-user-system-and-load "nyxt-user/dark-reader"
  :components ("dark-reader.lisp")
  :depends-on (:nx-dark-reader))


;; (define-configuration :prompt-buffer-mode
;;   "Add basic keybindings for prompt-buffer."
;;   ((keyscheme-map
;;     (keymaps:define-keyscheme-map
;;         "custom" (list :import %slot-value%)
;;       nyxt/keyscheme:emacs
;;       (list "C-j" 'nyxt/mode/prompt-buffer:next-suggestion
;;             "C-k" 'nyxt/mode/prompt-buffer:previous-suggestion)))))


;; (define-configuration buffer
;;   ((search-engines
;;     (list
;;      (make-instance 'search-engine
;;                     :shortcut "s"
;;                     :search-url "https://search.tfcconnection.org/?q=~a"
;;                     :fallback-url "https://search.tfcconnection.org")))))

;;; Loading files from the same directory.
(define-nyxt-user-system-and-load nyxt-user/basic-config
  :components ("status" "style"))
