#!/usr/bin/bash

set -f
set -o pipefail
PROGNAME=${0##*/}

DEFAULT_TYPES=(
    canvas-element
    canvas-workpad
    dashboard
    index-pattern
    lens
    map
    query
    search
    tag
    visualization
)

function exit_usage() {
    local status=${1:-0}
    [[ $status != 0 ]] && exec >&2
    echo "\
Usage: $PROGNAME [OPTION...] [SPACE-ID...]
List objects in spaces

Available options:
    -s, --space             Filter by space
    -t, --type              Filter by type
    --tsv                   Enable TSV output
    -h, --help              Display this help

Default filtered types:"
    echo "${DEFAULT_TYPES[*]}" |sort -u |fold -s -w 50 |
        sed -e 's! !, !g' -e 's,^,    ,'
    exit "$status"
}

function error() { echo "ERROR: $*" >&2; }
function fatal() { echo "FATAL: $*" >&2; exit 2; }

# $1: space
function list_objects() {
    local space=$1 curlopts=( --get ) t data page=0 stop
    for t in "${TYPES[@]}"; do
        curlopts+=( --data-urlencode "type=$t" )
    done
    while :; do
        (( ++page ))
        data=$(kbn-curl "/s/$space/api/saved_objects/_find?page=$page" "${curlopts[@]}") ||
            { error "Failed to list objects in space ${space@Q}"; return 1; }
        echo "$data"
        stop=$(echo "$data" |jq -r 'try (if .page * .per_page >= .total then 1 else 0 end) catch 1')
        [[ $stop == 1 ]] && break
    done |
        jq -r --arg space "$space" '.saved_objects |
            map("\($space)\t\(.type)\t\(.id)\t\(.attributes.title//.attributes.name//"")")[]'
}

function format_output() {
    if [[ -n $TSV ]]; then
        cat
    else
        local IFS=$'\t'
        while read -r space type id rest; do
            printf '%s:%s:%s\t%s\n' "$space" "$type" "$id" "$rest"
        done |LC_ALL=en_US.UTF-8 column -t -s $'\t'
    fi |
        sort -V
}

SPACES=()
TYPES=()
TSV=
while (( $# > 0 )); do
    case "$1" in
        -s|--space) SPACES+=( "$2" ); shift ;;
        -t|--type) TYPES+=( "$2" ); shift ;;
        --tsv) TSV=1 ;;
        -h|--help) exit_usage 0 ;;
        --) shift; break ;;
        -*) exit_usage 1 ;;
        *) SPACES+=( "$1" ) ;;
    esac
    shift
done
SPACES+=( "$@" )

if [[ -z $TYPES ]]; then
    TYPES=( "${DEFAULT_TYPES[@]}" )
fi

if [[ -z $SPACES ]]; then
    SPACES=( $(kbn-curl /api/spaces/space |jq -r 'map(.id) |sort[]') )
    [[ -z $SPACES ]] && fatal 'Failed to list spaces'
fi

{   gret=0
    for space in "${SPACES[@]}"; do
        list_objects "$space" || gret=1
    done
    (( gret == 0 ))
} |format_output

exit ${PIPESTATUS[0]}
