#!/usr/bin/env zsh

# Utility functions
function map () {
    local riverctl="${4}"
    if [[ "${riverctl}" = 'sd-spawn' ]]; then
        riverctl map "${1}" "${2}" "${3}" spawn \
                 "systemd-run --user --ignore-failure -- ${5}"
    else
        riverctl map "${@}"
    fi
}
function nmap () {
    map normal "${@}"
}
function input() {
    local pattern="${1}"
    for prop value in ${@:2}; do
        riverctl input "${pattern}" "${prop}" "${value}"
    done
}
function spawn () {
    riverctl spawn "${${@}}"
}
function sd-spawn () {
    riverctl spawn "systemd-run --user --G -- %{%{@}}"
}
local SCRIPT_DIR="${HOME}/scripts/"
local RIVER_CONFIG="${HOME}/.config/river/config/"

local mod=Super

# Some standard programs
nmap ${mod}       R      spawn    'systemd-run --user -G --scope fuzzel --launch-prefix="systemd-run --user -G --"'
nmap ${mod}+Shift Return sd-spawn 'kitty -1'
nmap ${mod}+Shift E      sd-spawn 'emacsclient -nc'
nmap ${mod}+Shift B      sd-spawn 'mullvad-browser'
# nmap ${mod}+Shift D      spawn 'gtk-pipe-viewer'
nmap ${mod}+Shift D      sd-spawn 'freetube --new-window'
nmap ${mod}+Shift O      sd-spawn 'loginctl lock-session'
nmap ${mod}+Shift P      sd-spawn 'keepassxc'
nmap ${mod}+Shift M      sd-spawn 'emacsclient -nc --eval "(mu4e)"'
nmap ${mod}+Shift C      sd-spawn 'kitty -1 ikhal'
nmap ${mod}+Shift R      sd-spawn "${SCRIPT_DIR}/wayland-screenshot.sh"
nmap ${mod}+Shift N      sd-spawn "${SCRIPT_DIR}/system-menu/system-menu.sh"

# Fcitx5 (this also works for waybar)
nmap ${mod} Space  spawn "${SCRIPT_DIR}/status-bar/sb-fcitx5-toggle ${RIVER_CONFIG}"

# Dunst bindings
nmap ${mod}         U spawn 'dunstctl close'
nmap ${mod}+Shift   U spawn 'dunstctl context'
nmap ${mod}+Control U spawn 'dunstctl history-pop'
nmap ${mod}+Control+Shift U spawn 'dunstctl close-all'

# ${mod}+Shift+T to show the systray
nmap ${mod}+Shift T spawn "pkill -RTMIN+4 waybar"

# ${mod}+X to close the focused view
nmap ${mod} X close

# ${mod}+Shift+Q to exit river
nmap ${mod}+Shift Q sd-spawn "${SCRIPT_DIR}/system-menu/confirm-logout.sh"

# ${mod}+J and ${mod}+K to focus the next/previous view in the layout stack
nmap ${mod} J focus-view next
nmap ${mod} K focus-view previous

# ${mod}+Shift+J and ${mod}+Shift+K to swap the focused view with the next/previous
# view in the layout stack
nmap ${mod}+Shift J swap next
nmap ${mod}+Shift K swap previous

# ${mod}+Period and ${mod}+Comma to focus the next/previous output
nmap ${mod} Period focus-output previous
nmap ${mod} Comma focus-output next

# ${mod}+Shift+{Period,Comma} to send the focused view to the next/previous output
nmap ${mod}+Shift Period send-to-output -current-tags previous
nmap ${mod}+Shift Comma send-to-output -current-tags next

# ${mod}+Return to bump the focused view to the top of the layout stack
nmap ${mod} Return zoom

# ${mod}+H and ${mod}+L to decrease/increase the main ratio of rivertile(1)
nmap ${mod} H send-layout-cmd rivertile "main-ratio -0.05"
nmap ${mod} L send-layout-cmd rivertile "main-ratio +0.05"

# ${mod}+Shift+H and ${mod}+Shift+L to increment/decrement the main count of rivertile(1)
nmap ${mod}+Shift H send-layout-cmd rivertile "main-count +1"
nmap ${mod}+Shift L send-layout-cmd rivertile "main-count -1"

# ${mod}+Alt+{H,J,K,L} to move views
nmap ${mod}+Alt H move left 100
nmap ${mod}+Alt J move down 100
nmap ${mod}+Alt K move up 100
nmap ${mod}+Alt L move right 100

# ${mod}+Alt+Control+{H,J,K,L} to snap views to screen edges
nmap ${mod}+Alt+Control H snap left
nmap ${mod}+Alt+Control J snap down
nmap ${mod}+Alt+Control K snap up
nmap ${mod}+Alt+Control L snap right

# ${mod}+Alt+Shift+{H,J,K,L} to resize views
nmap ${mod}+Alt+Shift H resize horizontal -100
nmap ${mod}+Alt+Shift J resize vertical 100
nmap ${mod}+Alt+Shift K resize vertical -100
nmap ${mod}+Alt+Shift L resize horizontal 100

# ${mod} + Left Mouse Button to move views
riverctl map-pointer normal ${mod} BTN_LEFT move-view

# ${mod} + Right Mouse Button to resize views
riverctl map-pointer normal ${mod} BTN_RIGHT resize-view

# ${mod} + Middle Mouse Button to toggle float
riverctl map-pointer normal ${mod} BTN_MIDDLE toggle-float

# ${mod} + Tab to switch between two sets of tags
nmap ${mod} Tab focus-previous-tags

for ((i = 1; i <= 9; ++i)); do
    let tags=$((1 << (${i} - 1)))

    # ${mod}+[1-9] to focus tag [0-8]
    nmap ${mod} ${i} set-focused-tags ${tags}

    # ${mod}+Shift+[1-9] to tag focused view with tag [0-8]
    nmap ${mod}+Shift ${i} set-view-tags ${tags}

    # ${mod}+Control+[1-9] to toggle focus of tag [0-8]
    nmap ${mod}+Control ${i} toggle-focused-tags ${tags}

    # ${mod}+Shift+Control+[1-9] to toggle tag [0-8] of focused view
    nmap ${mod}+Shift+Control ${i} toggle-view-tags ${tags}
done

# ${mod}+0 to focus all tags
# ${mod}+Shift+0 to tag focused view with all tags
let all_tags=$(((1 << 32) - 1))
nmap ${mod} 0 set-focused-tags ${all_tags}
nmap ${mod}+Shift 0 set-view-tags ${all_tags}

# ${mod}+Space to toggle float
nmap ${mod}+Shift Space toggle-float

# ${mod}+F to toggle fullscreen
nmap ${mod} F toggle-fullscreen

# ${mod}+{Up,Right,Down,Left} to change layout orientation
nmap ${mod} Up    send-layout-cmd rivertile "main-location top"
nmap ${mod} Right send-layout-cmd rivertile "main-location right"
nmap ${mod} Down  send-layout-cmd rivertile "main-location bottom"
nmap ${mod} Left  send-layout-cmd rivertile "main-location left"

# Declare a passthrough mode. This mode has only a single mapping to return to
# normal mode. This makes it useful for testing a nested wayland compositor
riverctl declare-mode passthrough

# ${mod}+F11 to enter passthrough mode
nmap ${mod} F11 enter-mode passthrough

# ${mod}+F11 to return to normal mode
map passthrough ${mod} F11 enter-mode normal

# Control volume
nmap None  XF86AudioRaiseVolume spawn "${SCRIPT_DIR}/sound-control.sh up 5%"
nmap Shift XF86AudioRaiseVolume spawn "${SCRIPT_DIR}/sound-control.sh up 1%"
nmap None  XF86AudioLowerVolume spawn "${SCRIPT_DIR}/sound-control.sh down 5%"
nmap Shift XF86AudioLowerVolume spawn "${SCRIPT_DIR}/sound-control.sh down 1%"
nmap None  XF86AudioMute        spawn "${SCRIPT_DIR}/sound-control.sh mute"

map locked None  XF86AudioRaiseVolume spawn "${SCRIPT_DIR}/sound-control.sh -n up 5%"
map locked Shift XF86AudioRaiseVolume spawn "${SCRIPT_DIR}/sound-control.sh -n up 1%"
map locked None  XF86AudioLowerVolume spawn "${SCRIPT_DIR}/sound-control.sh -n down 5%"
map locked Shift XF86AudioLowerVolume spawn "${SCRIPT_DIR}/sound-control.sh -n down 1%"
map locked None  XF86AudioMute        spawn "${SCRIPT_DIR}/sound-control.sh -n mute"

nmap None  KP_Prior spawn "${SCRIPT_DIR}/sound-control.sh up 5%"
nmap Shift KP_Prior spawn "${SCRIPT_DIR}/sound-control.sh up 1%"
nmap None  KP_Home  spawn "${SCRIPT_DIR}/sound-control.sh down 5%"
nmap Shift KP_Home  spawn "${SCRIPT_DIR}/sound-control.sh down 1%"
nmap None  KP_Up    spawn "${SCRIPT_DIR}/sound-control.sh mute"

map locked None  KP_Prior spawn "${SCRIPT_DIR}/sound-control.sh -n up 5%"
map locked Shift KP_Prior spawn "${SCRIPT_DIR}/sound-control.sh -n up 1%"
map locked None  KP_Home  spawn "${SCRIPT_DIR}/sound-control.sh -n down 5%"
map locked Shift KP_Home  spawn "${SCRIPT_DIR}/sound-control.sh -n down 1%"
map locked None  KP_Up    spawn "${SCRIPT_DIR}/sound-control.sh -n mute"

# Control screen backlight brightness
nmap None XF86MonBrightnessUp   spawn "${SCRIPT_DIR}/brightness-control.sh up 5%"
nmap None XF86MonBrightnessDown spawn "${SCRIPT_DIR}/brightness-control.sh down 5%"

map locked None XF86MonBrightnessUp   spawn "${SCRIPT_DIR}/brightness-control.sh -n up 5%"
map locked None XF86MonBrightnessDown spawn "${SCRIPT_DIR}/brightness-control.sh -n down 5%"

for mode in normal locked; do
    # Control MPRIS aware media players with playerctl
    map ${mode} None XF86AudioMedia spawn 'playerctl play-pause'
    map ${mode} None XF86AudioPlay  spawn 'playerctl play-pause'
    map ${mode} None XF86AudioPrev  spawn 'playerctl previous'
    map ${mode} None XF86AudioNext  spawn 'playerctl next'
done

# Use server-side decorations for everything by default
riverctl rule-add 'ssd'

# Set background and border color
riverctl background-color '0x002b36'
riverctl border-color-focused '0xff0000'
riverctl border-color-unfocused '0x586e75'

# Set keyboard repeat rate
riverctl set-repeat 50 300

# Some cursor options
riverctl focus-follows-cursor "normal"
riverctl set-cursor-warp "on-focus-change"

# Input options
input '*_Touchpad' \
       disable-while-typing 'disabled' \
       click-method 'clickfinger' \
       drag 'enabled' \
       middle-emulation 'enabled' \
       natural-scroll 'enabled' \
       tap 'enabled' \
       tap-button-map 'left-right-middle' \
       scroll-method 'two-finger'
input '*' \
      accel-profile 'flat'

# Make caps lock act as control
riverctl keyboard-layout \
         -options 'caps:ctrl_modifier' \
         'us'

# Set the default layout generator to be rivertile (started by systemd)
riverctl default-layout rivertile

# Use xwayland-satellite by default
export DISPLAY=:1

# Update the some environment variables
systemctl --user import-environment WAYLAND_DISPLAY DISPLAY
dbus-update-activation-environment WAYLAND_DISPLAY DISPLAY

# Notify systemd that we have setup River
systemd-notify --ready

"${SCRIPT_DIR}/emacs-server-import-environment.el" WAYLAND_DISPLAY DISPLAY

# The following is a list of units to enable:
# systemctl --user enable waybar.service
# systemctl --user enable fcitx5.service
# systemctl --user enable dunst.service
# systemctl --user enable polkit-mate-authentication-agent-1.service
# systemctl --user enable kanshi.service
# systemctl --user enable systembus-notify.service
# systemctl --user enable swayidle.service
# systemctl --user enable swaybg.service
# systemctl --user enable khal-notify.service
# systemctl --user enable inhibit-sleep-for-audio.service
# systemctl --user enable rivertile.service
# systemctl --user enable xwayland-satellite.service

# Laptop only:
# systemctl --user enable laptop-lid-daemon.service
# systemctl --user enable usbguard-notify.service

# Tray apps:
# systemctl --user enable tray-apps.target
# systemctl --user enable keepassxc.service
# systemctl --user enable nextcloud.service
# systemctl --user enable corectrl.service
# systemctl --user enable solaar.service
# systemctl --user enable protonmail-bridge.service
# systemctl --user enable blueman-applet.service
# systemctl --user enable safeeyes.service
