#!/bin/bash

#Log Function
log() {
    echo "$*"
}

logdbg() {
    if [ $dbg -eq 1 ]; then
        echo -e "DBG: $*"
    fi
}

loginfo() {
    echo "INFO: $*"
}

logerr() {
    echo -e "ERROR: $*"
}

#Jq Function
jqfunc() {
    local ljson=$1
    local jsdata
    local -a cmd=("jq" "-cnMS")
    local desc
    shift 1

    while (( "$#" )); do
        local key=_$1
        local val=$2
        local isfloat='^[0-9]+\.[0-9]+$'
        local isnumber='^[0-9]+$'
        local isobject='^\s*?\{.+?\}|^\s*?\[.+?\]'
        desc="$desc $1:\$$key,"

        if [[ $val =~ $isnumber ]] || [[ $val =~ $isfloat ]] || [[ $val =~ $isobject ]]; then
            cmd+=( "--argjson" "$key" "$val" )
        else
            cmd+=( "--arg" "$key" "$val" )
        fi
        shift 2
    done
    logdbg "desc={$desc}"
    logdbg "cmd=${cmd[@]}"
    jsdata=$("${cmd[@]}" "{ $desc }")

    eval $ljson="'${jsdata}'"
    return $?
}

#Sub Functions
getEapidata() {
    local ljson=$1
    local jsondata
    local leapifun=$2

    jsondata=$(herosuit $leapifun)
    if [[ $? != 0 ]]; then
        jsondata=""
    else
        jsondata=$(echo $jsondata | cut -d"|" -f3 | sed -e 's/^ //g;s/initializing\|finishing\|debug_level: 0//g;')
    fi

    eval $ljson="'$jsondata'"
}

getHwmCpuCore() {
    local ljson=$1
    local jsondata
    local onejson
    local jsonkey="ext name type value"
    local ext name type value
    ext=0
    type=7

    local cmd=$(cat <(grep 'cpu[0-9]' /proc/stat) <(sleep 0.05 && grep 'cpu[0-9]' /proc/stat))
    local cnt=0
    local np=$(nproc)
    for i in $(seq 0 $((np-1))); do
        name="Cpu$cnt"
        value=$(echo "$cmd" | grep "cpu$cnt " | awk -v RS="" '{printf("%3.2f"),($13-$2+$15-$4)*100/($13-$2+$15-$4+$16-$5)}')
        tojson=()
        for key in $jsonkey; do
            tojson+=("$key" "${!key}")
        done
        jqfunc onejson "${tojson[@]}"

        let cnt++
        if [ $cnt == 1 ]; then
            jsondata="$onejson"
        else
            jsondata="$jsondata,$onejson"
        fi
    done

    eval $ljson="'$jsondata'"
}

getHwmMem() {
    local ljson=$1
    local jsonkey="ext name type value"
    local ext name type value
    ext=0
    name="memory"
    type=8

    local cmd=$(cat /proc/meminfo | head -n 3 | sed 's/\s+/\s/g')
    value=$(echo $cmd | awk '{printf("%5.2f"),100*($2-$8)/$2}')

    tojson=()
    for key in $jsonkey; do
        tojson+=("$key" "${!key}")
    done
    jqfunc $ljson "${tojson[@]}"
}

getHwmStorage() {
    local ljson=$1
    local jsondata
    local onejson
    local jsonkey="ext name type value"
    local ext name type value
    ext=0
    name=
    type=10

    local cmd=$(df -h)
    local cnt=0
    while read -r line; do
        local fs=$(echo $line | awk '{printf("%s"),$1}')
        name=$(echo $line | awk '{printf("%s"),$6}')
        value=$(echo $line | sed 's/%//g' | awk '{printf("%s"),$5}')
        if [[ $fs == *"/"* ]]  && [[ ! $fs == *"loop"* ]] && [[ ! $name == *"media"* ]]; then
            tojson=()
            for key in $jsonkey; do
                tojson+=("$key" "${!key}")
            done
            jqfunc onejson "${tojson[@]}"

            let cnt++
            if [ $cnt == 1 ]; then
                jsondata="$onejson"
            else
                jsondata="$jsondata,$onejson"
            fi
        fi
    done <<< "$cmd"

    eval $ljson="'$jsondata'"
}

getSensors() {
    local ljson=$1
    local jsondata
    local sensor mem cpu storage

    getEapidata sensor --sensor
    getHwmMem mem
    getHwmCpuCore cpu
    getHwmStorage storage

    eval $ljson="'[${cpu},${mem},${storage},${sensor}]'"
}

#Part Functions
getHwmonitor() {
    local ljson=$1
    local jsonkey="$topjsonkey hwm"

    local hwm
    getSensors hwm
    [[ -z "$hwm" ]] && { logerr "empty hwm string"; return 1; }

    tojson=()
    for key in $jsonkey; do
        tojson+=("$key" "${!key}")
    done
    jqfunc $ljson "${tojson[@]}"

    return $?
}

#Tool
returnJson() {
    local lcatogory=$1
    local linfojson

    case "$lcatogory" in
        "hwm")
            getHwmonitor linfojson
            ;;
    esac

    log "$linfojson"
    if [[ ! -z ${linfojson} ]]; then
        mosquitto_pub -h $SERVER_IP -t hmi/$uuid/$lcatogory -m "$linfojson" || { exit 1; }
    else
        logerr "empty infojson"
        exit 1
    fi
    exit 0
}

#Main
while [ $# -gt 0 ] ; do
    case "$1" in
        -v | --version)
            log "1.0.0"
            shift 1
            exit 0
            ;;
        *)
            shift 1
            break
            ;;
    esac
done

declare -a tojson
declare -i dbg=0
declare -i cnt=0
declare SERVER_IP="localhost"
declare PRODUCT_UUID=$(cat /sys/class/dmi/id/product_uuid)
declare PRODUCT_NAME=$(cat /sys/class/dmi/id/board_name)
declare HWM_TIMER=5

#Device Information Check
if [ -z $PRODUCT_UUID ] || [ -z $PRODUCT_NAME ]; then
    logerr "Fail getting device information"
    exit 1
fi

#Top Level
uuid=${PRODUCT_UUID^}
ver="2.1.0"
topjsonkey="uuid ver ts"
while true; do
    ts=$(($(date +%s%N)/1000000))

    if [ $cnt -eq 0 ]; then
        ts2=$(($(date +%s%N)/1000000))
        returnJson "hwm" &
    else
        if [ $((ts-ts2)) -gt $((HWM_TIMER*1000)) ]; then
            ts2=$(($(date +%s%N)/1000000))
            returnJson "hwm" &
        fi
    fi
    let cnt++
done
