#!/bin/bash

json() {
    if [[ -n "$3" ]]; then
        echo -n "{\"name\":\"$1\",\"color\":\"$3\",\"full_text\":\"$2\"},"
    else
        echo -n "{\"name\":\"$1\",\"full_text\":\"$2\"},"
    fi
}

status_net() {
    local netvms=$(qvm-ls --no-spinner --raw-data --fields NAME,FLAGS 2>/dev/null | grep '|...N....$' | cut -d '|' -f1)

    IFS_BAK=$IFS
    IFS=$'\n'
    for netvm in $netvms; do
        local ip_addr=$(qvm-run "$netvm" -p 'ip -o -f inet addr' 2>/dev/null)
        for ip_addr_line in $ip_addr; do
            local device_name=${ip_addr_line#* }
            device_name=${device_name%% *}

            if [[ $device_name == wl* ]]; then # this is a wifi device
                local net=$(qvm-run $netvm -p 'iwconfig' 2>/dev/null)
                local ssid=$(echo "$net" | perl -ne 'print "$1" if /ESSID:"(.*)"/')
                local ip=${ip_addr_line#* inet }
                ip=${ip%%/*}
                if [[ -n $ssid ]]; then
                    local quality=$(echo "$net" | perl -ne 'print "$1" if /Quality=([^ ]+)/')
                    json $device_name "$netvm: $ssid $ip $quality"
                fi
            elif [[ $device_name == en* ]]; then # this is an ethernet device
                local ip=${ip_addr_line#* inet }
                ip=${ip%%/*}
                json $device_name "$netvm: $ip"
            fi
        done
    done
    IFS=$IFS_BAK
    IFS_BAK=
}

status_time() {
    local time=$(date '+%F %T')
    echo -n "{\"name\":\"time\",\"full_text\":\"$time\"}" # last entry
}

status_bat() {
    local accum_now_mWh=0 # current battery power in mWh
    local accum_full_mWh=0 # full battery power in mWh

    local batteries # batteries connected to the system
    mapfile -t batteries < <(shopt -s nullglob; for f in /sys/class/power_supply/BAT*; do echo "$f"; done)
    for battery in "${batteries[@]}"; do
        if [ -f "${battery}"/energy_now ]; then
            accum_now_mWh=$((accum_now_mWh + $(cat "${battery}"/energy_now)))
            accum_full_mWh=$((accum_full_mWh + $(cat "${battery}"/energy_full)))
        elif [ -f $battery/charge_now ]; then
            # charge is given in mAh, convert to mWh
            local voltage=$(cat "${battery}"/voltage_now)
            local now_mWh=$(((voltage / 1000) *  $(cat "${battery}"/charge_now) / 1000))
            local full_mWh=$(((voltage / 1000) *  $(cat "${battery}"/charge_full) / 1000))

            accum_now_mWh=$((accum_now_mWh + now_mWh))
            accum_full_mWh=$((accum_full_mWh + full_mWh))
        fi
    done

    local bat_pct=$((100*accum_now_mWh/accum_full_mWh))

    local ac_present=false

    local adps # power adapters connected to the system
    mapfile -t adps < <(shopt -s nullglob; for f in /sys/class/power_supply/ADP* \
                                                    /sys/class/power_supply/AC* ; do echo "$f"; done)
    for adp in ${adps[@]}; do
        if [[ $(cat "${adp}"/online) == '1' ]]; then
            ac_present=true
        fi
    done

    local color=''
    if [[ "$ac_present" == true ]]; then
        ac=' AC'
    elif ((bat_pct < 25)); then
        color='#ff0000'
    elif ((bat_pct < 50)); then
        color='#ffff00'
    fi

    json bat "Bat: $bat_pct%$ac" "$color"
}

status_load() {
    local load=$(uptime)
    load=${load/#*load average: }
    load=${load%,*,*}
    json load "Load: $load"
}

status_qubes() {
    local qubes=$(qvm-ls --no-spinner --raw-data --fields FLAGS 2>/dev/null | grep -v '^0' | grep '^.r......' | wc -l)
    json qubes "$qubes Qubes"
}

status_disk() {
    local disk=''
    local free=''
    local size=''
    local usage=''
    read size usage <<< $(qvm-pool -i $(qubes-prefs default-pool) | grep 'size\|usage' | sort | awk '{print $2}')
    free=$(($size - $usage))
    case ${#free} in
        1[3-5])
            disk="$(($free / 1099511627776))T" ;;
        1[0-2])
            disk="$(($free / 1073741824))G" ;;
        [7-9])
            disk="$(($free / 1048576))M" ;;
        [4-6])
            disk="$(($free / 1024))K" ;;
        [1-3])
            disk="$free Bytes" ;;
        *)
            disk="Error" ;;
    esac
    json disk "Disk free: $disk"
}

status_volume() {
    local volume=$(awk '/%/ {gsub(/[\[\]]/,""); print $4}' <(amixer sget Master))
    local playback=$(awk '/%/ {gsub(/[\[\]]/,""); print $6}' <(amixer sget Master))
    if [[ $playback == off ]]; then
        json volume "Volume: mute"
    else
        json volume "Volume: $volume"
    fi
}

main() {
    echo '{"version":1}'
    echo '['
    echo '[]'
    local n
    for ((n=0; ; ++n)); do
        if (( n % 10 == 0 )); then
            local qubes=$(status_qubes)
            # network status disabled by default as it's dangerous to run a
            # command on a qube from dom0
            # local net=$(status_net)
            local disk=$(status_disk)
            local bat=$(status_bat)
            local load=$(status_load)
            local volume=$(status_volume)
        fi
        local time=$(status_time)
        echo ",[$qubes$disk$bat$load$volume$time]"
        sleep 1
    done
}


main
