#!/bin/bash

# This file contains all the cursors used for the different tests
JOURNALCTL_CURSOR_FILE="$SPREAD_PATH"/tests/runtime-state/journalctl_cursor

show_help() {
    echo "usage: journal-state start-new-log"
    echo "       journal-state check-log-started"
    echo "       journal-state get-last-cursor"
    echo "       journal-state match-log [expression]"
    echo "       journal-state get-log"
    echo "       journal-state get-log-from-cursor"
}

get_last_cursor(){
    journalctl --output=export -n1 | grep --binary-files=text -o '__CURSOR=.*' | sed -e 's/^__CURSOR=//'
}

start_new_log(){
    _sync_log
    echo "New test starts here - $SPREAD_JOB" | systemd-cat -t snapd-test
    cursor=$(get_last_cursor)
    if [ -z "$cursor" ]; then
        echo "Empty journalctl cursor, exiting..."
        exit 1
    else
        echo "$SPREAD_JOB " >> "$JOURNALCTL_CURSOR_FILE"
        echo "$cursor" >> "$JOURNALCTL_CURSOR_FILE"
    fi
}

check_log_started(){
    marker="test-${RANDOM}${RANDOM}"
    echo "Running test: $marker" | systemd-cat -t snapd-test
    if match_log "$marker"; then
        return 0
    fi
    echo "Test id not found in journalctl, exiting..."
    exit 1
}

match_log(){
    expression=$1
    shift
    for _ in $(seq 10); do
        # forcibly silence this particular bit because it produces GOBS of 
        # output and we really don't need to see all the output when we are 
        # checking the output for an expression, as if it is missing we want to 
        # check the journal once at the end of this loop, likely in the debug 
        # section
        set +x
        log=$(get_log "$@")
        if echo "$log" | grep -q -E "$expression"; then
            return 0
        fi
        set -x
        echo "Match for \"$expression\" failed, retrying"
        sleep 1
    done
    return 1
}

get_log(){
    cursor=""
    if [ -f "$JOURNALCTL_CURSOR_FILE" ]; then
        cursor=$(tail -n1 "$JOURNALCTL_CURSOR_FILE")
    fi
    _sync_log
    get_log_from_cursor "$cursor" "$@"
}

get_log_from_cursor(){
    cursor=$1
    shift
    if [ -z "$cursor" ]; then
        journalctl "$@"
    else
        journalctl "$@" --cursor "$cursor"
    fi
}

_sync_log(){
    journalctl --flush || true
    journalctl --sync || true
}

main() {
    if [ $# -eq 0 ]; then
        show_help
        exit 0
    fi

    subcommand=$1
    action=
    while [ $# -gt 0 ]; do
        case "$1" in
            -h|--help)
                show_help
                exit 0
                ;;
            *)
                action=$(echo "$subcommand" | tr '-' '_')
                shift
                break
                ;;
        esac
    done

    if [ -z "$(declare -f "$action")" ]; then
        echo "journal-state: no such command $subcommand" >&2
        show_help
        exit 1
    fi

    "$action" "$@"
}

main "$@"
