;; -*-lisp-*-
;;
;; StumpWM config

(in-package :stumpwm)

(defparameter *key-layout* "us -variant altgr-intl" "Stores the current key layout")

;; creating or rename groups
(setf (group-name (first (screen-groups (current-screen)))) "web")
(gnewbg "work")
(gnewbg "misc")
(gnewbg "music")
(gnewbg "winkel")

;; border width
(setf *maxsize-border-width* 3)
(setf *transient-border-width* 3)
(setf *normal-border-width* 3)

;; border style
(setf *window-border-style* :tight)
(set-focus-color "#b00045")
(set-win-bg-color "#b00045")
(set-unfocus-color "#333333")
(set-float-focus-color "#b00045")
(set-float-unfocus-color "#333333")

;; window gravity
(set-normal-gravity :center)
(set-maxsize-gravity :center)
(set-transient-gravity :center)
(gravity :center)

;; input bar position
(setf *input-window-gravity* :center)

;; message bar position
(setf *message-window-gravity* :center)

;; message timeout
(setf *timeout-wait* 3)

;; set the mouse focus
(setf *mouse-focus-policy* :click)

;; set DESKTOP_SESSION variable
(setf (getenv "DESKTOP_SESSION") "stumpwm")

;; style message windows
(set-bg-color "#333333")
(set-border-color "#b00045")

;; loading modeline modules
(load-module "battery-portable")
(load-module "hostname")
(load-module "stumptray")

;; mode-line style
(setf *mode-line-background-color* "#333333"
      *mode-line-foreground-color* "#cccccc"
      *mode-line-border-color* "#b00045"
      *mode-line-timeout* 5
      *mode-line-border-width* 3
      *mode-line-pad-x* 3
      *mode-line-pad-y* 3
      *screen-mode-line-format* (list "[" '(:eval (RUN-SHELL-COMMAND "date '+%F %H:%M'|tr -d [:cntrl:]" T)) "] [%n]  %w ^> [" '(:eval (RUN-SHELL-COMMAND "hostname -I |tr -d [:cntrl:]" T)) "][%B] [marcel@%h] %T"))

;; customize texts
(setf *window-format* "^B %n ^b %20t "
      *group-format* "%t")

;; program runners

;;; emacs
(defcommand emacs () ()
            "run emacs"
            (run-or-raise "es" '(:class "Emacs")))

;; root keybindings
;
;; browser
(define-key *root-map* (kbd "W") "exec x-www-browser")
(define-key *root-map* (kbd "P") "exec firefox-nightly --private-window")

;;; terminal
(define-key *root-map* (kbd "c") "exec urxvt")

;;; es as emacs
(define-key *root-map* (kbd "e") "emacs")

;;; ranger
(define-key *root-map* (kbd "C-c") "exec nemo --no-desktop")

;;; spotify
(define-key *root-map* (kbd "m") "exec spotify")

;;; bind keys for changing workspace
(define-key *root-map* (kbd "C-1") "change-workspace web")
(define-key *root-map* (kbd "C-2") "change-workspace work")
(define-key *root-map* (kbd "C-3") "change-workspace misc")
(define-key *root-map* (kbd "C-4") "change-workspace music")
(define-key *root-map* (kbd "C-s") "change-workspace winkel")

;; bind keys for moving the current window to another workspace
(define-key *root-map* (kbd "M-1") "gmove web")
(define-key *root-map* (kbd "M-2") "gmove work")
(define-key *root-map* (kbd "M-3") "gmove misc")
(define-key *root-map* (kbd "M-4") "gmove music")
(define-key *root-map* (kbd "M-s") "gmove winkel")

;;; mode-line key
(define-key *root-map* (kbd "Menu") "mode-line")

;; define volume control keys
(define-key *top-map* (kbd "XF86AudioLowerVolume") "exec amixer set Master 5%-")
(define-key *top-map* (kbd "XF86AudioRaiseVolume") "exec amixer set Master 5%+")
(define-key *top-map* (kbd "XF86AudioMute") "exec amixer set Master toggle")
(define-key *top-map* (kbd "XF86AudioMicMute") "exec amixer set Capture toggle")

;; webjump keys
(defvar *webjump-frame-bindings*
  (let  ((m (make-sparse-keymap)))
    (define-key m (kbd "g") "google")
    (define-key m (kbd "G") "googlede")
    (define-key m (kbd "d") "duckduckgo")
    (define-key m (kbd "D") "packages")
    (define-key m (kbd "w") "wikipedia")
    (define-key m (kbd "W") "wikipediade")
    m))

(define-key *root-map* (kbd "j") '*webjump-frame-bindings*)

;; lockscreen
(define-key *root-map* (kbd "M-l") "exec blurlock")

;; battery status
(define-key *root-map* (kbd "b") "exec ~/scripts/rat/bat.sh")

;; xserver

(run-shell-command "xrdb -merge ~/.Xresources")
;;; HiDPI stuff.
;;; TODO: Only run if required
;; (run-shell-command "xrdb -merge ~/.Xresources-hidpi")

;; dunst notify server
(run-shell-command "dunst")

;; nitrogen (wallpaper)
(run-shell-command "nitrogen --restore")

;; start mode line
;; (if (not (head-mode-line (current-head)))
;;     (toggle-mode-line (current-screen) (current-head)))

;; set backlight
(defcommand set-backlight (value)
  ((:string "Backlight in %: "))
  "Setting a new value for the backlight"
  (run-shell-command (concatenate 'string "xbacklight -set " value))
  (echo (concatenate 'string "Backlight set to " value)))

(define-key *root-map* (kbd "B") "set-backlight")

;; tweet
(defcommand tweet (tweet)
  ((:string "Tweet: "))
  "Tweet"
  (run-shell-command (concatenate 'string "cd ~/programs/dart/learning/twitter && dart main.dart -t \"" tweet "\""))
  (echo (concatenate 'string "Tweeted: " tweet)))

(define-key *root-map* (kbd "T") "tweet")

;; switch key layout
(defun switch-layout-to (new-lang)
  "Switch the key layout to the given one"
  (setq *key-layout* new-lang)
  (run-shell-command (concatenate 'string "setxkbmap -layout " new-lang " && xmodmap ~/.Xmodmap"))
  (echo (concatenate 'string "Set keyboard layout to " new-lang)))

;; switch key leyout to german
(defcommand layout-de ()
  ()
  "Set the keyboard layout to de (german)"
  (switch-layout-to "de"))

;; switch key leyout to american english
(defcommand layout-en ()
  ()
  "Set the keyboard layout to US International AltGr"
  (switch-layout-to "us -variant altgr-intl"))

;; switch key layout automatically
(defcommand switch-layout ()
  ()
  "Switch the layout"
  (if (string= "us -variant altgr-intl" *key-layout*)
      (switch-layout-to "de")
      (switch-layout-to "us -variant altgr-intl")))

(define-key *top-map* (kbd "s-SPC" ) "switch-layout")

;; switch workspace with a message
(defcommand change-workspace (n)
  ((:string n))
  "Switch workspace"
  (run-commands (concatenate 'string "gselect " n))
  (echo (concatenate 'string "Switched to " n)))

;; toggle window floating
(defcommand toggle-float ()
  ()
  "Toggle weather window is floating or not"
  (if (typep (current-window) 'STUMPWM::FLOAT-WINDOW)
      (unfloat-this)
      (float-this)))

;; and the key for it
(define-key *root-map* (kbd "C-f") "toggle-float")

;; key for keeping window always on top
(define-key *root-map* (kbd "^") "toggle-always-on-top")

;; working with emacsclient
(defvar *es-win* nil
  "to hold the window called emacsclient")
(defun save-es-called-win ()
  (setf *es-win* (current-window)))

(defun return-es-called-window (win)
  (let* ((group (window-group win))
	 (frame (window-frame win))
	 (old-frame (tile-group-current-frame group)))
    (frame-raise-window group frame win)
    (focus-all win)
    (unless (eq frame old-frame)
      (show-frame-indicator group))))

;; webjumps
(defmacro make-web-jump (name prefix)
  `(defcommand ,(intern name) (search) ((:rest ,(concatenate 'string name " search: ")))
    (substitute #\+ #\Space search)
    (run-shell-command (concatenate 'string ,prefix search))))

(make-web-jump "google" "firefox-nightly http://www.google.com/search?q=")
(make-web-jump "googlede" "firefox-nightly  http://www.google.de/search?q=")
(make-web-jump "duckduckgo" "firefox-nightly https://duckduckgo.com/?q=")
(make-web-jump "packages" "firefox-nightly https://packages.debian.org/search?suite=sid&searchon=names&keywords=")
(make-web-jump "wikipedia" "firefox-nightly https://en.wikipedia.org/w/index.php?search=")
(make-web-jump "wikipediade" "firefox-nightly https://de.wikipedia.org/w/index.php?search=")
(defun list-screen-layouts ()
  "Return an alist of possible screen layouts. Those are the layouts saved in
~/.screenlayout.sh. First is the name of the layout and second the path to the
script."
  (loop
     for file
     in (mapcar 'namestring
		(directory "~/.screenlayout/*.sh"))
     collect `(,(subseq file
			(+ 1 (search "/" file :from-end t))
			(- (length file) 3))
		,file)))

(defcommand switch-screen-layout ()
  ()
  "Menu to switch the screen layout. Possible options are the scripts saved in
  ~/.screenlayout/"
  (labels
      ((pick (options)
	 (let ((selection
		(select-from-menu
		 (current-screen)
		 options
		 nil
		 0)))
	   (cond
	     ((null selection)
	      nil)
	     (t (stringp (second selection))
		(run-shell-command (second selection)))))))
    (pick (list-screen-layouts))))

(define-key *root-map* (kbd "l") "switch-screen-layout")

;; font configuration
(load-module "ttf-fonts")
(set-font (make-instance 'xft:font :family "Hack" :subfamily "Regular" :size 10))

;; window placement rules
(define-frame-preference "winkel"
  (0 nil t :class "keepassxc")
  (0 nil t :class "ownCloud")
  (0 nil t :class "de-dal33t-Start")
  (0 nil t :class "TelegramDesktop")) ;; bwSyncAndShare

(define-frame-preference "web"
  (0 nil t :class "Nightly"))

(define-frame-preference "music"
  (0 nil t :class "Spotify"))

;; autostart programs

;; keepassxc
(run-shell-command "gpg --textmode -d ~/.config/keepassxc/password.gpg | keepassxc --pw-stdin ~/ownCloud/keys/2017-10.kdbx")

;; owncloud
(run-shell-command "owncloud")

;; bwSyncAndShare
(run-shell-command "bwsyncandshare")

;; firefox
(run-shell-command "firefox-nightly")

;; telegram
(run-shell-command "telegram-desktop")

;; emacs
(run-commands "emacs")

;; redshift
(run-shell-command "redshift")

;; last settings
;; (stumptray:stumptray)

(switch-layout-to *key-layout*)

(run-shell-command "xmodmap $HOME/.Xmodmap" t)