#!/usr/bin/bash

# heos-groups  Copyright 2025-2026  Norman Carver

# Script program to print (to stdout) information about the current (online) HEOS Groups.
#
# Sends commands to the default HEOS master device, but can select alternative
# using the MASTER_IPNUM argument option.


function print_usage()
{
    echo -e "Print information about the current HEOS Groups.\n" >&2
    echo    "Usage: heos-groups [-n] [-s] [MASTER_IPNUM]" >&2
    echo    "where:" >&2
    echo    "  MASTER_IPNUM -- use a non-default HEOS master device;" >&2
    echo -e "  (IPNUM means the last quad of an IP address only: i.e., 0--255.)\n" >&2
    echo    "Options:" >&2
    echo    "  -n -- names: print out only group Names;" >&2
    echo    "  -s -- sort: print out groups info sorted by names (uses system sort command);" >&2
}


if [[ "$1" == --help ]]; then
    print_usage
    exit 0
fi

# Process supplied options:
names=false
sort=false
debugopt=""
while [[ "$1" == -* ]]; do
    if [[ "$1" == -n ]]; then
        names=true
    elif [[ "$1" == -s ]]; then
        sort=true
    elif [[ "$1" == -- ]]; then
        shift;break
    elif [[ "$1" == --debug ]]; then
        debugopt=--debug
    else
        echo "Error: invalid option '$1'" >&2
        echo "(use '--' to signal end of options, with -* arguments)" >&2
        exit 1
    fi
    shift
done

# Process command arguments:
if [[ $# -gt 1 ]]; then
    print_usage
    exit 1
fi

if [[ $# == 1 ]]; then
    master=${1}
else
    master=""
fi
heosdir=$(dirname "$0")


# heosutil-run-command error checking function (one json output):
# args: 1) command result variable; 2) error message; [3) error action]
# (default action on error is 'exit 1', use $3 of 'return 1' to continue execution)
function error_check_run_command()
{
    cmdresult=${!1}
    if [[ ($? != 0) || ("$cmdresult" != *'"result": "success"'*) ]]; then
        if [[ "$cmdresult" == Error:* || ($debugopt == --debug && "$cmdresult" == ERROR:*) ]]; then
            echo "$cmdresult" >&2
        fi
        if [[ -n "$2" ]]; then echo "$2" >&2; fi
        if [[ $# == 3 ]]; then $3; else exit 1; fi
    else
        return 0
    fi
}


# Get Groups info (in JSON format):
groupsjson=$("$heosdir"/heosutils/heosutil-run-command "heos://group/get_groups" $master)
error_check_run_command groupsjson "Error: failed getting HEOS Groups!"

# Extract Payload info:
payload=$(grep -Eo '"payload": .+\}\]\}\]\}' <<< "$groupsjson")

# Use grep to make line-based list of the groups:
groupslist=$(grep -Eo '\{"name": [^]]+\}\]\}' <<<"$payload")

# Sort players (by name) if -s option:
if $sort; then
    groupslist=$(sort <<<"$groupslist")
fi

if ! $names; then
    # Reformat and print out groups info:
    {   cnt=0
        while read line; do
            name=${line#*\"name\":\ \"}
            name=${name%%\",*}
            gid=${line#*\"gid\":\ }
            gid=${gid%%[,\}]*} # handle comma or end-brace
            gid=${gid//\"/}   # remove quotes if present
            cnt=$((cnt + 1))
            printf "%2d) Group '%s'  GID:%s:\n" $cnt "$name" "$gid"
            playerslist=$(grep -Eo '\{[^}]+\}' <<<"${line#*\"players\":\ \[}")
            while read player; do
                p_name=${player#*\"name\":\ \"}
                p_name=${p_name%%\",*}
                pid=${player#*\"pid\":\ }
                pid=${pid%%[,\}]*}
                pid=${pid//\"/}
                role=${player#*\"role\":\ \"}
                role=${role%%\"*}
                echo "      player: '$p_name'  ($role)  PID:$pid"
            done <<< "$playerslist"
        done
    } <<<"$groupslist"

else
    # Print out groups names:
    { while read line; do
          line=${line#*\"name\":\ \"}
          echo "${line%%\"[,\}]*}"
      done 
    } <<< "$groupslist"

fi

#EOF
