#!/usr/bin/env bash
{ set +x; } 2>/dev/null

usage() {
    echo "usage: $(basename $0)" 1>&2
    [ "$1" = "-h" ] || [ "$1" = "--help" ]; exit
}

[ "$1" = "-h" ] || [ "$1" = "--help" ] && usage "$@"

IFS=
f1="$(mktemp)" || exit
f2="$(mktemp)" || exit
list="$(launchctl list | awk '{print $2, $3}')" || exit
agents="$(find ~/Library/LaunchAgents -name "*.plist" -exec sh -c 'Label="$(/usr/libexec/PlistBuddy -c "Print Label" {} 2> /dev/null)"; [[ -n $Label ]] && echo "{}|$Label"' ';')"

unloaded="$(while IFS= read a; do
    IFS='|';set $a; [[ "$list" != *"$2"* ]] && echo "$1"
done <<< "$agents")"
Gray="$([[ -n "$unloaded" ]] && while IFS= read f; do
    while [[ $f == ~/Library/* ]] && [[ $f != ~/Library ]]; do echo $f; f="${f%/*}"; done
done <<< "$unloaded" | sort -u)"

err_status="$(while IFS= read a; do
    IFS='|';set $a; path="$1"; label="$2"; IFS=
    [[ "$list" == *"$label"* ]] && { echo "$list" | grep -q "0 $label"$ || echo "$path"; }
done <<< "$agents")"
Red="$([[ -n "$unloaded" ]] && while IFS= read f; do
    while [[ $f == ~/Library/* ]] && [[ $f != ~/Library ]]; do echo $f; f="${f%/*}"; done
done <<< "$err_status" | sort -u)"

err_log="$(find ~/Library/LaunchAgents -name "*.plist" -exec sh -c 'path="$(/usr/libexec/PlistBuddy -c "Print StandardErrorPath" "{}" 2> /dev/null)"; [ -s "$path" ] && echo {}' ';')"
Orange="$([[ -n "$unloaded" ]] && while IFS= read f; do
    while [[ $f == ~/Library/* ]] && [[ $f != ~/Library ]]; do echo $f; f="${f%/*}"; done
done <<< "$err_log" | sort -u)"

for tag in Gray Red Orange; do
    paths="${!tag}"
    tag --find "$tag" ~/Library/LaunchAgents > "$f1" || exit
    ! [ -s "$f1" ] && echo $'\n' > "$f1"
    echo "$paths" > "$f2" || exit
    add="$(awk 'FNR==NR{array[$0];next}{if ($1 in array) next;print $1}' "$f1" "$f2")" || exit
    rm="$(awk 'FNR==NR{array[$0];next}{if ($1 in array) next;print $1}' "$f2" "$f1")" || exit
    [[ -n "$add" ]] && { IFS=$'\n';set $add; tag --add "$tag" "$@" || exit; }
    [[ -n "$rm" ]] && { IFS=$'\n';set $rm; tag --remove "$tag" "$@" || exit; }
done;:
