#!/bin/sh -efu

if [ -z "${__included_altera_sh_functions:-}" ]; then
__included_altera_sh_functions=1

backend4_allowed_actions=" list read write "

exec 3>&1

_write_end()
{
    printf '\n_message:end\n' >&3
}

write_error_json()
{
    jq -cn --arg error "$1" '{error: $error}' >&3
}

json_get()
{
    printf '%s\n' "${in_action_payload}" | jq "$@"
}

backend4_dispatch()
{
    local request_json="$1"
    local action_name action_payload handler

    action_name="$(printf '%s\n' "$request_json" | jq -er '
        .action
        | select(type == "object")
        | del(._objects)
        | keys_unsorted
        | select(length == 1)
        | .[0]
    ')" || {
        write_error_json "invalid backend4 request: exactly one action is required"
        return 1
    }

    case " $backend4_allowed_actions " in
        *" $action_name "*) ;;
        *)
            write_error_json "unsupported action: $action_name"
            return 1
            ;;
    esac

    action_payload="$(printf '%s\n' "$request_json" | jq -c --arg action "$action_name" '.action[$action]')"

    in_action="$action_name"
    in_action_payload="$action_payload"
    handler="on_$action_name"

    if command -v "$handler" >/dev/null 2>&1; then
        "$handler"
    elif command -v on_message >/dev/null 2>&1; then
        on_message
    else
        write_error_json "handler not implemented for action: $action_name"
        return 1
    fi
}

message_loop_backend4()
{
    local line
    exec 1>&2
    while IFS= read -r line; do
        [ -n "$line" ] || continue
        backend4_dispatch "$line" || :
        _write_end
    done
}

fi # __included_altera_sh_functions
