#!/bin/sh
# umbriel-smart-move left|right
# niri's consume-or-expel move, extended across outputs:
#   - stacked in a column      → expel to a new column on that side
#   - alone, column beside it   → consume into that column
#   - alone, at the strip's end → move to the output on that side
# Pressing twice therefore steps a window past its neighbour: in, then out the
# far side. Dwindle and master workspaces have no columns; there the window
# moves in that direction, or onto the next output at the edge. Floating and
# scratchpad windows are left alone.
set -eu

case ${1:-} in
left | right) dir=$1 ;;
*) echo "usage: umbriel-smart-move left|right" >&2; exit 2 ;;
esac

windows=$(umbriel windows --json)
layout=$(umbriel workspaces --json | jq -r '.[] | select(.focused) | .layout')

# "<action>" for the focused window, or nothing when it should stay put.
action=$(printf '%s' "$windows" | jq -r --arg dir "$dir" --arg layout "$layout" '
    (map(select(.focused)) | first) as $w
    | if $w == null or $w.floating or $w.scratchpad != "" then empty
      elif $layout != "scrolling" then "window-move-or-output-\($dir)"
      else
        [ .[] | select(.workspace == $w.workspace and (.floating | not) and .scratchpad == "") ] as $tiled
        | ([ $tiled[] | select(.column == $w.column) ] | length) as $rows
        | ([ $tiled[] | .column ] | if $dir == "left" then min else max end) as $edge
        | if $rows > 1 or $w.column != $edge then "window-consume-or-expel-\($dir)"
          else "window-move-or-output-\($dir)"
          end
      end')

[ -n "$action" ] || exit 0
# At the outermost output, "no output to the left/right" is the expected end.
umbriel msg "$action" >/dev/null 2>&1 || true
