;;; app/irc/autoload/email.el -*- lexical-binding: t; -*-

(defvar +irc--workspace-name "*IRC*")

(defun +irc-setup-wconf (&optional inhibit-workspace)
  (unless inhibit-workspace
    (+workspace-switch +irc--workspace-name t))
  (let ((buffers (doom-buffers-in-mode 'circe-mode nil t)))
    (if buffers
        (ignore (switch-to-buffer (car buffers)))
      (require 'circe)
      (delete-other-windows)
      (switch-to-buffer (doom-fallback-buffer))
      t)))

;;;###autoload
(defun =irc (&optional inhibit-workspace)
  "Connect to IRC and auto-connect to all registered networks.

If INHIBIT-WORKSPACE (the universal argument) is non-nil, don't spawn a new
workspace for it."
  (interactive "P")
  (cond ((and (featurep! :ui workspaces)
              (+workspace-exists-p +irc--workspace-name))
         (+workspace-switch +irc--workspace-name))
        ((not (+irc-setup-wconf inhibit-workspace))
         (user-error "Couldn't start up a workspace for IRC")))
  (if (doom-buffers-in-mode 'circe-mode (buffer-list) t)
      (message "Circe buffers are already open")
    (if circe-network-options
        (cl-loop for network in circe-network-options
                 collect (circe (car network)))
      (call-interactively #'circe))))

;;;###autoload
(defun +irc/connect (&optional inhibit-workspace)
  "Connect to a specific registered server.

If INHIBIT-WORKSPACE (the universal argument) is non-nil, don't spawn a new
workspace for it."
  (interactive "P")
  (and (+irc-setup-wconf inhibit-workspace)
       (call-interactively #'circe)))

;;;###autoload
(defun +irc/send-message (who what)
  "Send WHO a message containing WHAT."
  (interactive "sWho: \nsWhat: ")
  (circe-command-MSG who what))

;;;###autoload
(defun +irc/quit ()
  "Kill current circe session and workgroup."
  (interactive)
  (if (y-or-n-p "Really kill IRC session?")
      (let (circe-channel-killed-confirmation
            circe-server-killed-confirmation)
        (when +irc--defer-timer
          (cancel-timer +irc--defer-timer))
        (disable-circe-notifications)
        (mapc #'kill-buffer (doom-buffers-in-mode 'circe-mode (buffer-list) t))
        (when (equal (+workspace-current-name) +irc--workspace-name)
          (+workspace/delete +irc--workspace-name)))
    (message "Aborted")))

;;;###autoload
(defun +irc/ivy-jump-to-channel (&optional this-server)
  "Jump to an open channel or server buffer with ivy. If THIS-SERVER (universal
argument) is non-nil only show channels in current server."
  (interactive "P")
  (if (not (circe-server-buffers))
      (message "No circe buffers available")
    (when (and this-server (not circe-server-buffer))
      (setq this-server nil))
    (ivy-read (format "Jump to%s: " (if this-server (format " (%s)" (buffer-name circe-server-buffer)) ""))
              (cl-loop with servers = (if this-server (list circe-server-buffer) (circe-server-buffers))
                       with current-buffer = (current-buffer)
                       for server in servers
                       collect (buffer-name server)
                       nconc
                       (with-current-buffer server
                         (cl-loop for buf in (circe-server-chat-buffers)
                                  unless (eq buf current-buffer)
                                  collect (format "  %s" (buffer-name buf)))))
              :action #'+irc--ivy-switch-to-buffer-action
              :preselect (buffer-name (current-buffer))
              :keymap ivy-switch-buffer-map
              :caller '+irc/ivy-jump-to-channel)))

(defun +irc--ivy-switch-to-buffer-action (buffer)
  (when (stringp buffer)
    (ivy--switch-buffer-action (string-trim-left buffer))))

;;;###autoload
(defun +irc/tracking-next-buffer ()
  "Dissables switching to an unread buffer unless in the irc workspace."
  (interactive)
  (when (derived-mode-p 'circe-mode)
    (tracking-next-buffer)))


;;
;;; Hooks/fns

;;;###autoload
(defun +circe-buffer-p (buf)
  "Return non-nil if BUF is a `circe-mode' buffer."
  (with-current-buffer buf
    (and (derived-mode-p 'circe-mode)
         (eq (safe-persp-name (get-current-persp))
             +irc--workspace-name))))

;;;###autoload
(defun +irc--add-circe-buffer-to-persp-h ()
  (when (bound-and-true-p persp-mode)
    (let ((persp (get-current-persp))
          (buf (current-buffer)))
      ;; Add a new circe buffer to irc workspace when we're in another workspace
      (unless (eq (safe-persp-name persp) +irc--workspace-name)
        ;; Add new circe buffers to the persp containing circe buffers
        (persp-add-buffer buf (persp-get-by-name +irc--workspace-name))
        ;; Remove new buffer from accidental workspace
        (persp-remove-buffer buf persp)))))
