#!/usr/bin/env zsh

function update-workspaces {
    if ((${urgent} != 0)); then
        jq -e --null-input \
            --argjson 'active' "${active}" \
            --argjson 'urgent' "${urgent}" \
            'any($active.[]; .active == $urgent)' >/dev/null && urgent=0
    fi
    jq --null-input -c \
        --argjson 'existing' "${existing}" \
        --argjson 'active_id' "${active}" \
        --argjson 'always_show' '[1,2,3,4,5,6,7,8,9]' \
        --argjson 'urgent_id' "${urgent}" \
        '$existing | map_values([.[], ($always_show.[] |
                                      {id: ., name: . | tostring, windows: 0, monitor: null})] |
                                       unique_by(.name) |
                                       map((.monitor != null and
                                           .id == $active_id.[.monitor].active) as $active |
                                           (.id == $urgent_id and ($active | not) and .monitor != null) as $urgent |
                                           if (((.name | startswith(".")) and ($active | not))
                                              or ((.name == "special") and (.id == -99))) then empty else
                                           .class = (if $active then "hypr-ws-button-active"
                                                     else if $urgent then "hypr-ws-button-urgent"
                                                     else "hypr-ws-button" end end) |
                                           .changecmd = ((try "~/.config/hypr/scripts/switch-workspace switch \(.name | tonumber)"
                                                          catch empty) // "hyprctl dispatch workspace \(.id)") end))'
}

function get-workspaces {
    hyprctl -j workspaces | \
        jq '[group_by(.monitor).[] | {(.[0].monitor): (. | .[0].monitor as $mon | map({id: .id, windows: .windows, name: .name, monitor: $mon}))}] | add'
}

function get-active {
    hyprctl -j monitors | \
        jq -c 'map({(.name): {active: .activeWorkspace.id}}) | add'
}

# args: (address: string)
function get-workspace-for-window-address {
    hyprctl -j clients | jq --arg 'addr' "0x${1}" \
        '.[] | select(.address == $addr) | .workspace.id'
}

function handle {
    case "${1}" in
        urgent\>\>*)
            urgent="$(get-workspace-for-window-address "${1:8}")"
            update-workspaces
            ;;
        workspace\>\>*)
            active="$(get-active)"
            update-workspaces
            ;;
        openwindow*|closewindow*|*workspace*|movewindow*)
            existing="$(get-workspaces)"
            update-workspaces
            ;;
    esac
}

let urgent=0
local active="$(get-active)"
local existing="$(get-workspaces)"
update-workspaces
socat -U - "unix-connect:/tmp/hypr/${HYPRLAND_INSTANCE_SIGNATURE}/.socket2.sock" |
    while read line; do
        handle "${line}"
    done