#!/usr/bin/env zsh

indent="  "

# Ref: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1
function skip-crap {
    local crap_start="^Object [^ ]+ \(.*\), has been already finalized. Impossible to \w* any property \w* it.*"

    local crap_continue=(
        "^== Stack trace for context.*"
        "^#[0-9]+\s*0x.*"
    )

    local skip=0
    local skipped=0
    local begin_skip_date

    # Could probably be done more elegantly with awk/sed ?
    while read -r date; do
        read -r line
        if [[ $line =~ $crap_start ]]; then
            # echo setting skip
            skip=1
            begin_skip_date=$date
            ((skipped += 1))
            continue
        fi

        if [[ $skip == 1 ]]; then
            if [[ ($line =~ $crap_continue[1]) ||
                      ($line =~ $crap_continue[2]) ]]; then
                ((skipped += 1))
                continue
            else
                # echo reset skip
                printf "%s\n" $begin_skip_date
                printf "${indent}Skipped \"already finalized\" crap ($skipped lines)\n"
                skip=0
                skipped=0
            fi
        fi

        printf "%s\n%s\n" $date $line
    done
}

function group-stack-traces {
    local addr="0x[0-9a-z]+"
    local start_pattern="== Stack trace for context ${addr} =="
    local stackframe="^#[0-9]+\s*${addr}"
    local in_group=0
    while read -r date; do
        read -r line;

        if [[ $line =~ $start_pattern ]]; then
            in_group=1
        elif ! [[ $line =~ $stackframe ]]; then
            in_group=0
        fi

        if [[ $in_group == 0 ]]; then
            printf "%s\n" $date
        fi

        printf "${indent}%s\n" $line
    done
}

function date-on-separate-line {
    # Use line buffering to be able to interactively grep the output
    # (sed use line buffering when stdout is tty, but doesn't detect this
    # transiently so `debug | grep foobar` will run without line buffering
    # without the stdbuf stuff)
    stdbuf -oL sed -e "s|\]:|]:\n${indent}|"
}

# We use non-breaking space to encode newlines in multiline messages
function decode-multiline-message {
    stdbuf -oL sed -e 's| |\n    |g'
}

function gnome-shell-exe-path {
    if uname -a | grep --silent "NixOS"; then
        echo $(dirname =gnome-shell(:A))/.gnome-shell-wrapped
    else
        echo =gnome-shell
    fi
}

# Skip journalctl "logs start at.." to not disrupt date,line,date,line stream
function skip-header {
    stdbuf -oL tail -n +2
}

journalctl --follow --lines 400 $@ $(gnome-shell-exe-path) \
    | skip-header              \
    | date-on-separate-line    \
    | skip-crap                \
    | group-stack-traces       \
    | decode-multiline-message 

