#!/bin/sh

set -u

source /lib/functions/navico_env.sh
source /lib/functions/upd_datestamp.sh
source /usr/libexec/nos-hal/storage.sh
navico_env_init

show_usage() {
    cat >&2 <<EO_USAGE
Usage: ${0##*/} FUNCTION [ARGS]

	FUNCTION	ARGS
	burnin-status	{in-progress|completed|overtime|error|exit}
	hdmi-output	{enable|disabled-hdcp}
	ethernet	{get-config|set-config <IP>}
	sonar		{powerdown|stop|restart <args>|start <args>|is-running}
	prepare-update	{<path/to/updater>}
	codename
	factory-datestamp
	dump-syslog     <output-file>
	dump-dmesg      <output-file>
	ftp-download    {serverip local-file remote-file}
	eth-dhcp-mode   {client|server}
	get-storage-type
	get-storage-details {emmc|nand}
	language-pack   {reset <lang>}
EO_USAGE
}

show_ethernet_usage() {
    cat >&2 <<EO_USAGE
Usage: ${0##*/} FUNCTION [ARGS]

        FUNCTION	ARGS
        get-config
        set-config	{<IP>}

EO_USAGE
}

IP_INTERFACE_ALIAS="eth0:lwe"
IP_INTERFACE="eth0"

ip_in_range() {
    printf '%s ' "$@" | awk '
        function ip2int(ip) {
            res=0;
            split(ip, a, ".");
            for (n=1 ; n<=4; n++) {
                v=a[n];

                if (v !~ /^[0-9]+$/ || v > 255) {
                    exit 1;
                }

                res=256*res + v;
            }

            return res;
        }

        {
            lo=ip2int($1);
            hi=ip2int($2);
            ip=ip2int($3);

            if ( ip < lo || ip > hi ) exit 2;
        }'
}

ethernet_set() {
    if ip_in_range 172.16.0.0 172.31.255.255 $1; then
        sudo -n /sbin/ip address flush label ${IP_INTERFACE_ALIAS} dev ${IP_INTERFACE}
        sudo -n /sbin/ip address add $1/16 label ${IP_INTERFACE_ALIAS} dev ${IP_INTERFACE}
        return
    fi
    return 2
}

ethernet_get() {
    local ip_addr=$(/sbin/ip address show label ${IP_INTERFACE_ALIAS} | awk -F" " '/inet/ {print substr($2, 0, index($2, "/")-1)}')
    if [ -n "${ip_addr}" ]; then
        echo "${ip_addr}"
        return
    fi
    return 1
}

ethernet () {
    local command=${1:-}

    case $command in
    set-config)
        shift && ethernet_set "$@"
        ;;
    get-config)
        ethernet_get
        ;;
    *)
        printf 'Unsupported argument "%s"\n' "$command"
        show_ethernet_usage
        return 1
        ;;
    esac
}

burnin_status_hatchetfish() {
    local state="$1"
    local led_cmd=34
    local cpu=$((SUBFAMILYID - 1))
    local green_led=1
    local red_led=2
    local both_leds=3
    local colour2=0
    local priority duty_ms colour1

    case "$state" in
    in-progress)
        priority=11
        duty_ms=150
        colour1="$both_leds"
        ;;
    completed)
        priority=10
        duty_ms=150
        colour1="$green_led"
        ;;
    overtime)
        priority=12
        duty_ms=50
        colour1="$both_led"
        ;;
    error)
        priority=14
        duty_ms=50
        colour1="$red_led"
        ;;
    exit)
        priority=0
        duty_ms=0
        colour1=0
        ;;
    *)
        printf 'Unsupported burnin-status "%s"\n' "$status" 1>&2
        return 1
        ;;
    esac

    duty_ms=$((duty_ms / 10)) # mcu-util wants tens of ms
    echo "t $led_cmd $cpu $priority $colour1 $duty_ms $colour2 $duty_ms" | mcu-util
}

burnin_status_komodo() {
    local state="$1"
    local red_led_path=/sys/class/leds/status-red
    local green_led_path=/sys/class/leds/status-green

    set_timer_trigger() {
        local led_path="$1"
        local duty_ms="$2"
        echo timer > "${led_path}/trigger"
        echo "$duty_ms" > "${led_path}/delay_on"
        echo "$duty_ms" > "${led_path}/delay_off"
    }

    local led_path
    case "$state" in
    in-progress)
        for led_path in "$red_led_path" "$green_led_path"; do
            set_timer_trigger "$led_path" 150
        done
        ;;
    completed)
        echo none > "${red_led_path}/trigger"
        echo 0 > "${red_led_path}/brightness"
        set_timer_trigger "$green_led_path" 150
        ;;
    overtime)
        for led_path in "$red_led_path" "$green_led_path"; do
            set_timer_trigger "$led_path" 50
        done
        ;;
    error)
        set_timer_trigger "$red_led_path" 50
        echo none > "${green_led_path}/trigger"
        echo 0 > "${green_led_path}/brightness"
        ;;
    exit)
        for led_path in "$red_led_path" "$green_led_path"; do
            echo none > "${led_path}/trigger"
            echo 0 > "${led_path}/brightness"
        done
        ;;
    *)
        printf 'Unsupported burnin-status "%s"\n' "$status" 1>&2
        return 1
        ;;
    esac
}

burnin_status() {
    local args="$@"

    case "$FAMILYID" in
    Hatchetfish)
        burnin_status_hatchetfish "$args"
        ;;
    Komodo)
        burnin_status_komodo "$args"
        ;;
    *)
        ;;
    esac
}

hdmi_output() {
    local state=${1:-}
    local hdmi_disable=/run/shm/hdmi-output-disable

    case $state in
    enable)
        if [ -e "$hdmi_disable" ]; then
            rm "$hdmi_disable"
            /lib/udev/udev_hdmi_action.sh --probe
        fi
        ;;
    disabled-*)
        echo "$state" > "$hdmi_disable"
        /lib/udev/udev_hdmi_action.sh --probe
        ;;
    *)
        printf 'Unsupported argument "%s"\n' "$state"
        return 1
        ;;
    esac
}

ftp_download() {
    local server_ip=${1:-}
    local local_file=${2:-}
    local remote_file=${3:-}

    if [ -n "$local_file" -a -n "$remote_file" ]; then
        ftpget "$server_ip" -u ftp "$local_file" "$remote_file"
        return $?
    fi
    return 1
}

eth_dhcp_mode() {
    local dhcp_mode=${1:-}
    local dhcp_mode_file="/home/nos-hal/dhcp-mode"

    case $dhcp_mode in
    client|server)
        sudo -n /usr/libexec/nos-hal/set-dhcp-mode "$dhcp_mode"
        ;;
    "")
        if [ -r "$dhcp_mode_file" ]; then
            cat "$dhcp_mode_file"
        else
            case "$FAMILYID" in
            KomodoHub)
                echo "server"
                ;;
            *)
                echo "client"
                ;;
            esac
        fi
        ;;
    *)
        printf 'Unsupported argument "%s"\n' "$dhcp_mode"
        return 1;
        ;;
    esac
}

ALL_ARGS="$@"

case ${1:-} in
    hdmi-output)
        shift && hdmi_output "$@"
        ;;
    burnin-status)
        shift && burnin_status "$@"
        ;;
    ethernet)
        shift && ethernet "$@"
        ;;
    sonar)
        shift && sudo -n /usr/libexec/nos-hal/sonar "$@"
        ;;
    prepare-update)
        shift && sudo -n /usr/libexec/nos-hal/prepare-update "$@"
        ;;
    codename)
        echo "${CODENAME:-}"
        ;;
    factory-datestamp)
        get_factory_datestamp
        ;;
    dump-syslog)
        shift && { logread || cat /var/log/messages || cat /tmp/messages; } 2>/dev/null | tail -c 32768 > "$1"
        ;;
    ftp-download)
        shift && ftp_download "$@"
        ;;
    dump-dmesg)
        shift && /bin/dmesg > "$1"
        ;;
    eth-dhcp-mode)
        shift && eth_dhcp_mode "$@"
        ;;
    get-storage-type)
        shift && get_storage_type
        ;;
    get-storage-details)
        shift && get_storage_details "$@"
        ;;
    language-pack)
        shift && sudo -n /usr/libexec/nos-hal/language-pack "$@"
        ;;
    ""|-h|--help)
        show_usage
        exit 0
        ;;
    *)
        show_usage
        false
        ;;
esac

RESULT=$?
PARENT=$(tr '\0' '\t' </proc/$PPID/cmdline | cut -f1)
logger -t "${0##*/}" -p info -- "$PARENT[$PPID] $ALL_ARGS -> $RESULT"

exit $RESULT
