#!/usr/bin/bash

# heos-mkgroup  Copyright 2025-2026  Norman Carver

# Script program to make a new group from some (online) HEOS players.
#
# Sends commands to the default HEOS master device, but can select alternative
# using the MASTER_IPNUM argument option.


function print_usage()
{
    echo -e "Make a new group from some (online) HEOS Players.\n" >&2
    echo    "Usage: heos-mkgroup PLAYER_LIST [MASTER_IPNUM]" >&2
    echo    "where:" >&2
    echo    "  PLAYER_LIST -- comma-separated list of player names or IPNUMs, the first becoming the group leader;" >&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    "If a player name includes comma(s), PLAYER_LIST must use quotes:" >&2
    echo    "  heos-mkgroup 'player1,\"player2, w2quotes, in name\",player3'" >&2
}


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

# Catch invalid supplied options:
debugopt=""
while [[ "$1" == -* ]]; do
    if [[ "$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
done

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

plist=$1
if [[ $# == 2 ]]; then
    master=${2}
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
}


# heosutil-run-command error checking function (two json outputs):
# 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_2json()
{
    cmdresult=${!1}
    if [[ ($? != 0) || ("$cmdresult" != *'"result": "success"'*'"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 players info:
players=$("$heosdir"/heosutils/heosutil-run-command "heos://player/get_players" $master)
error_check_run_command players "Error: failed getting HEOS Players list!"

# Parse PLAYER_LIST and make PID list:
pidlist=
while [[ -n "$plist" ]]; do

    if [[ "$plist" == \"* ]]; then
        plist=${plist#\"}
        player=${plist%%\",*}
        plist=${plist#*\",}
    else
        player=${plist%%,*}
        plist=${plist#*,}
    fi
    if [[ "$plist" == "$player" ]]; then
        plist=""
    fi

    #Get PID for player:
    if [[ "$player" =~ ^[0-9]+$ ]]; then
        # PLAYER is a player ipnum, so get matching PID:
        matches=$(grep -Eio '\{[^{}]+"ip": "[0-9]+\.[0-9]+\.[0-9]+\.'"${player}"'"[^{}]+\}' <<<"$players")
        if [[ $? != 0 ]]; then
            echo "Error: PLAYER is an invalid player IPNUM: '$player'!" >&2
            exit 1
        fi
        matches=${matches#*\"pid\":\ }
        pid=${matches%%[,\}]*}
    else
        matches=$(grep -Eio '\{"name": "[^"]*'"${player}"'[^"]*"[^{}]+\}' <<<"$players")
        if [[ $? != 0 ]]; then
            echo "Error: PLAYER is an invalid player name: '$player'!" >&2
            exit 1
        fi
        matches=${matches#*\"pid\":\ }
        pid=${matches%%[,\}]*}
    fi

    #Add player PID to pidlist:
    if [[ "$pidlist" == "" ]]; then
        pidlist=$pid
    else
        pidlist=${pidlist},$pid
    fi
done

# Make a new group from a set of players:
result=$("$heosdir"/heosutils/heosutil-run-command --numjson=2 "heos://group/set_group?pid=$pidlist" $master)
error_check_run_command_2json result "Error: failed creating group!"

gid=${result#gid=}
gid=${gid%%[\"&]*}
echo "New group GID: $gid"

#EOF
