#!/bin/bash

# Parameters:
#
#   verify [iface] - checks if any update is needed on [iface] or on all detected modules
#   update [iface] - do the update on [iface] or on all detected modules
#   forget         - clear list of all detected modules
#
# Environment variables:
#
#   DEBUG_MODE - set to 1 enable debug messages to stderr
#
# Return codes:
#
#     0 - no update needed (verify) or success (update)
#     1 - modules need to be updated (verify)
#   123 - some fatal error occurred

export sngtc_tool="/usr/local/nsc/bin/sngtc_tool"

export sng_mod_path="/var/sng"
export sng_mod_base="modules."

sng_list_cache_ifaces()
{
    [ ! -d "$sng_mod_path" ] && return 0

    if [ $(find "$sng_mod_path" -name "${sng_mod_base}*" | grep -c '') = "0" ]; then
        # we don't have any cached modules, force a rescan for getting cached modules list
        /usr/local/sng/bin/sng-detect-transcoding-modules &> /dev/null
    fi

    find "$sng_mod_path" -name "${sng_mod_base}*" -printf '%f\n' | awk -F'.' '{ print $2 }'
}

sng_list_modules_helper()
{
    local logfile="${sng_mod_path}/${sng_mod_base}$1"

    [ -f "$logfile" ] && cat "$logfile"
}

sngtc_list_modules()
{
    sng_list_modules_helper "$1" | \
        awk '/MAC=/ { print gensub("([0-9]+)[.] MAC=([0-9a-f-]+).+Ver=([0-9a-zA-Z._-]+).*","\\1 \\2 \\3",1) }'
}

sngtc_fw_version()
{
    local ver=`$sngtc_tool -firmware_version | awk '/Vocallo / { print gensub(".+Vocallo ([0-9a-zA-Z._-]+).*", "\\\\1", 1) }'`

    [ -z "${ver}" ] && return 123

    [ -n "$DEBUG_MODE" ] && echo "debug: current version is ${ver}" >&2

    echo "$ver"
}

fw_up_update()
{
    while read dev; do
	# If it's a Sangoma DSP, try to disable the ext port to avoid duplicate module detection
        if [ "${dev:0:6}" = "sngdsp" ]; then
             $sngtc_tool -dev "${dev}" -disable-ext-ports
        fi

        echo "update($dev): Updating modules..."
        for i in 0 1 2; do
            $sngtc_tool -dev "${dev}" -firmware -silent && break
            [ $i = 2 ] && return 1
        done
        echo "update($dev): Waiting for modules to come back..."

        sleep 5
        echo "update($dev): Updating licenses on ${dev}..."
        for i in 0 1 2; do
            $sngtc_tool -dev "${dev}" -license -silent && break
            [ $i = 2 ] && return 1
            sleep 5
        done

        sleep 2
        echo "update($dev): Rebooting modules..."
        for i in 0 1 2; do
            $sngtc_tool -dev "${dev}" -reset -silent && break
            [ $i = 2 ] && return 1
            sleep 3
        done
        sleep 0.5

        if [ "${dev:0:6}" = "sngdsp" ]; then
             $sngtc_tool -dev "${dev}" -enable-ext-ports
        fi
    done
    return 0
}

fw_up_compare()
{
    local cur_ver="$1"
    local ret_val=0

    while IFS=" " read mod_num mod_mac mod_ver; do
        if [ "${mod_ver}" != "${cur_ver}" ]; then
            local new_ver=`(echo "${mod_ver}"; echo "${cur_ver}") | sort -nr | head -n1`

            [ -n "$DEBUG_MODE" ] && echo "debug: sorting between '${mod_ver}' and '${cur_ver}'..." >&2

            if [ "${new_ver}" = "${cur_ver}" ]; then
                echo "MAC=${mod_mac} Status=outdated"
                ret_val=1
            else
                echo "MAC=${mod_mac} Status=mismatch"
                ret_val=1
            fi
        else
            echo "MAC=${mod_mac} Status=ok"
        fi
    done

    return $ret_val
}

fw_up_verify_helper()
{
    local cur="$1"
    local ret=0

    while read dev; do
        sngtc_list_modules "${dev}" | fw_up_compare "${cur}"
        tmpret=$?

        [ "$tmpret" != "0" ] && ret=$tmpret
    done

    return $ret
}

fw_up_verify()
{
    local fwver=`sngtc_fw_version`

    [ -z "${fwver}" ] && return 123

    fw_up_verify_helper "${fwver}"
}

fw_up_main()
{
    local retnum=0

    if [ -z "$2" ]; then
        sng_list_cache_ifaces | "fw_up_$1"
        retnum=$?
    else
        echo "$2" | "fw_up_$1"
        retnum=$?
    fi

    return $retnum
}

fw_up_forget_modules()
{
    [ ! -d "$sng_mod_path" ] && return 0

    find "$sng_mod_path" -name "${sng_mod_base}*" -exec rm -f '{}' ';'
}

fw_up_lock()
{
    ( flock -x 123; "$@" ) 123<"$0"
}

if [ -z $1 ]; then
    mode="verify"
else
    mode=$1
fi

ret=1

case "$mode"
in
    "verify") fw_up_lock fw_up_main verify "$2"; ret=$? ;;
    "update") fw_up_lock fw_up_main update "$2"; ret=$? ;;
    "forget") fw_up_lock fw_up_forget_modules;   ret=$? ;;
    *)
        echo "usage: $0 verify|update [if]" >&2
        ret=123
    ;;
esac

exit $ret
