#!/usr/bin/env bash

set -e

AVAILABLE_MODES=(output window region)

function Help() {
    cat <<EOF
Usage: sway-screenshot [options ..] -m [mode] -- [command]

sway-screenshot is an utility to easily take screenshot in swaywm using your mouse.

It allows taking screenshots of windows, regions and monitors which are saved to a folder of your choosing and copied to your clipboard.

Options:
  -h, --help            show help message
  -m, --mode            one of: output, window, region
  -o, --output-folder   directory in which to save screenshot
  -f, --filename        the file name of the resulting screenshot
  -d, --debug           print debug information
  -s, --silent          don't send notification when screenshot is saved
  --clipboard-only      copy screenshot to clipboard and don't save image in disk
  -- [command]          open screenshot with a command of your choosing. e.g. sway-screenshot -m window -- mirage

Modes:
  output                take screenshot of an entire monitor
  window                take screenshot of an open window
  region                take screenshot of selected region
EOF
}

function Print() {
    if [ $DEBUG -eq 0 ]; then
        return 0
    fi
    
    1>&2 printf "$@" 
}

function send_notification() {
    if [ $SILENT -eq 1 ]; then
        return 0
    fi
    notify-send "Screenshot saved" \
                "Image saved in <i>${1}</i> and copied to the clipboard." \
                -i "${1}"
}

function save_geometry() {
    Print "Geometry: %s\n" "${1}"

    if [ $CLIPBOARD -eq 0 ]; then
        mkdir -p "$SAVEDIR"
        grim -g "${1}" "$SAVE_FULLPATH"
        local output="$SAVE_FULLPATH"
        # Trim transparent pixels, in case the window was floating and partially
        # outside the monitor
        convert $output -trim +repage $output
        wl-copy < "$output"
        send_notification $output
        [ -z "$COMMAND" ] || {
            "$COMMAND" "$output"
        }
    else
        wl-copy < <(grim -g "${1}" - | convert - -trim +repage -)
    fi
}

function begin_grab() {
    local option=$1
    case $option in
        output)
            local geometry=`grab_output`
            ;;
        region)
            local geometry=`grab_region`
            ;;
        window)
            local geometry=`grab_window`
            ;;
    esac
    save_geometry "${geometry}"
}

function grab_output() {
    slurp -or
}

function grab_region() {
    slurp -d
}

function grab_window() {
    local clients=`swaymsg -t get_tree | jq -r '[.. | ((.nodes? // empty) + (.floating_nodes? // empty))[] | select(.visible and .pid)]'`
    Print "Clients: %s\n" "$clients"
    # Generate boxes for each visible window and send that to slurp
    # through stdin
    local boxes="$(echo $clients | jq -r '.[] | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height) \(.name)"')"
    Print "Boxes:\n%s\n" "$boxes"
    slurp -r <<< "$boxes"
}

function args() {
    local options=$(getopt -o hf:o:m:ds --long help,filename:,output-folder:,mode:,clipboard-only,debug,silent -- "$@")
    eval set -- "$options"

    while true; do
        case "$1" in
            -h | --help)
                Help
                exit
                ;;
            -o | --output-folder)
                shift;
                SAVEDIR=$1
                ;;
            -f | --filename)
                shift;
                FILENAME=$1
                ;;
            -m | --mode)
                shift;
                echo "${AVAILABLE_MODES[@]}" | grep -wq $1
                OPTION=$1;;
            --clipboard-only)
                CLIPBOARD=1
                ;;
            -d | --debug)
                DEBUG=1
                ;;
            -s | --silent)
                SILENT=1
                ;;
            --)
                shift # Skip -- argument
                COMMAND=${@:2}
                break;;
        esac
        shift
    done

    if [ -z $OPTION ]; then
        Print "A mode is required\n\nAvailable modes are:\n\toutput\n\tregion\n\twindow\n"
        exit 2
    fi
}

if [ -z $1 ]; then
    Help
    exit
fi

CLIPBOARD=0
DEBUG=0
SILENT=0
FILENAME="$(date +'%Y-%m-%d-%H%M%S_sway-screenshot.png')"
[ -z "$SWAY_SCREENSHOT_DIR" ] && SAVEDIR=${XDG_PICTURES_DIR:=~} || SAVEDIR=${SWAY_SCREENSHOT_DIR}

args $0 "$@"

SAVE_FULLPATH="$SAVEDIR/$FILENAME"
[ $CLIPBOARD -eq 0 ] && Print "Saving in: %s\n" "$SAVE_FULLPATH"
begin_grab $OPTION
