#!/bin/bash
# console-config/src/lib-scripts/timing-ntp.sh
#
#  Copyright: ©2013–2014, Güralp Systems Ltd.
#  Author: Laurence Withers <lwithers@guralp.com>
#  License: GPLv3
#
# NTP setup. We allow add, edit and remove of servers, one at a time. After
# this, we run serial port setup to allow selection of an NMEA output port if
# desired.
#

# variables global to this file
declare -a NTP_SERVER_ADDRESSES
declare -a NTP_SERVER_ARGUMENTS



# ntp_add_server()
#  Allows the user to add a brand new server. As long as it is not a duplicate
#  then we add it to the NTP_SERVER_ADDRESSES array.
ntp_add_server() {
    local DUP
    local ADDRESS=""
    local ARGUMENTS="minpoll 4 maxpoll 4"

    while true
    do
        dialog --title "Add new NTP server" \
            --form "Enter the server address and any NTP arguments (default \
suggested arguments are \"minpoll 4 maxpoll 4\"). Use tab to switch between \
fields and buttons and use the arrow keys to navigate." 14 "${DIALOG_DEFAULT_W}" 4 \
            "Server address" 1 0 "${ADDRESS}" 2 2 32 64 \
            "Arguments" 3 0 "${ARGUMENTS}" 4 2 32 64 \
            2> "${DIALOG_RESULTFILE}"

        # take no action if dialog was cancelled
        [ $? -ne 0 ] && return 0

        ADDRESS="`head -n 1 "${DIALOG_RESULTFILE}"`"
        ARGUMENTS="`tail -n 1 "${DIALOG_RESULTFILE}"`"

        [ -z "${ADDRESS}" ] && return 0

        # check for duplicates
        DUP=0
        for ADDR_CHECK in "${NTP_SERVER_ADDRESSES[@]}"
        do
            if [ "${ADDRESS}" = "${ADDR_CHECK}" ]
            then
                DUP=1
                dialog --msgbox "Duplicate server address." 0 0
            fi
        done
        [ "${DUP}" -eq 0 ] || continue

        # OK; add a new result
        NTP_SERVER_ADDRESSES+=("${ADDRESS}")
        NTP_SERVER_ARGUMENTS+=("${ARGUMENTS}")
        return 0
    done
}



# ntp_save_config()
#  This writes out the new NTP configuration file. It then executes the serial
#  port configuration script.
save_config_aux() {
    local i=0
    for ADDRESS in "${NTP_SERVER_ADDRESSES[@]}"
    do
        ARGUMENTS="${NTP_SERVER_ARGUMENTS[${i}]}"
        ((++i))

        [ -z "${ADDRESS}" ] && continue
        echo "server ${ADDRESS} ${ARGUMENTS}"
    done
}

ntp_save_config() {
    clear

    (
        write_ntp_preamble
        local i=0
        local ADDRESS ARGUMENTS
        for ADDRESS in "${NTP_SERVER_ADDRESSES[@]}"
        do
            ARGUMENTS="${NTP_SERVER_ARGUMENTS[${i}]}"
            ((++i))

            [ -z "${ADDRESS}" ] && continue
            echo "server ${ADDRESS} ${ARGUMENTS}"
        done
    ) | write_config_file "${NTP_CONFIG}"

    write_timing_config "ntp" "true" "false" "false"

    svc timing restart

    serial_clear_input
    serial_clear_xlate
    serial_select_output "NTP"

    echo "Configuration updated."
    exit 0
}



# ntp_edit_server()
#  Allows the user to edit the address and/or arguments for a server, or to
#  delete the entry altogether. The server address to modify is passed as "$1".
#  Will modify NTP_SERVER_ADDRESSES and NTP_SERVER_ARGUMENTS.
ntp_edit_server() {
    local ADDR_CHECK ARGUMENTS DUP
    local ADDRESS="$1"
    local index=0

    for ADDR_CHECK in "${NTP_SERVER_ADDRESSES[@]}"
    do
        [ "${ADDR_CHECK}" = "${ADDRESS}" ] && break
        ((++index))
    done
    if [ "${NTP_SERVER_ADDRESSES[${index}]}" != "${ADDRESS}" ]
    then
        assert "ntp_edit_server cannot find server in list"
    fi

    ARGUMENTS="${NTP_SERVER_ARGUMENTS[${index}]}"

    while true
    do
        dialog --title "Edit NTP server" \
            --form "Alter the server address and any NTP arguments below. \
Leave the address empty to delete it. Use tab to switch between fields and \
buttons and use the arrow keys to navigate." 14 60 4 \
            "Server address" 1 0 "${ADDRESS}" 2 2 32 64 \
            "Arguments" 3 0 "${ARGUMENTS}" 4 2 32 64 \
            2> "${DIALOG_RESULTFILE}"

        # take no action if dialog was cancelled
        [ $? -ne 0 ] && return 0

        ADDRESS="`head -n 1 "${DIALOG_RESULTFILE}"`"
        ARGUMENTS="`tail -n 1 "${DIALOG_RESULTFILE}"`"

        # check for a deleted server
        if [ -z "${ADDRESS}" ]
        then
            unset NTP_SERVER_ADDRESSES[${index}]
            unset NTP_SERVER_ARGUMENTS[${index}]
            return 0
        fi

        # check for duplicates if we changed this server address
        if [ "${ADDRESS}" != "${NTP_SERVER_ADDRESSES[${index}]}" ]
        then
            DUP=0
            for ADDR_CHECK in "${NTP_SERVER_ADDRESSES[@]}"
            do
                if [ "${ADDRESS}" = "${ADDR_CHECK}" ]
                then
                    DUP=1
                    dialog --msgbox "Duplicate server address." 0 0
                fi
            done
            [ "${DUP}" -eq 0 ] || continue
        fi

        # OK; modify this result
        NTP_SERVER_ADDRESSES=([${index}]="${ADDRESS}")
        NTP_SERVER_ARGUMENTS=([${index}]="${ARGUMENTS}")
        return 0
    done

    return 0
}



# ntp_setup()
#  Main loop: user may add a new server, select an existing server to edit, or
#  save settings.
ntp_setup() {
    local i DIRECTIVE ADDRESS ARGUMENTS
    NTP_SERVER_ADDRESSES=()
    NTP_SERVER_ARGUMENTS=()

    # Read existing NTP server directives. We don't support any other directives,
    # just using our own fixed ones when we write the config file. If the NTP
    # config was previously using a refclock, then we'll have strange-looking
    # addresses: filter those out.
    while read -r DIRECTIVE ADDRESS ARGUMENTS
    do
        # filter out refclocks
        [ "${ADDRESS:0:8}" = "127.127." ] && continue

        # only catch server directives
        if [ "${DIRECTIVE}" = "server" ]
        then
            NTP_SERVER_ADDRESSES+=("${ADDRESS}")
            NTP_SERVER_ARGUMENTS+=("${ARGUMENTS}")
        fi
    done < "${NTP_CONFIG}"

    # Main menu loop, allowing add/edit/save.
    while true
    do
        i=0
        MENU=()
        for ADDRESS in "${NTP_SERVER_ADDRESSES[@]}"
        do
            ARGUMENTS="${NTP_SERVER_ARGUMENTS[${i}]}"
            ((++i))

            [ -z "${ADDRESS}" ] && continue
            MENU+=("${ADDRESS}")
            MENU+=("Edit (arguments: \"${ARGUMENTS}\")")
        done

        dialog --title "NTP configuration" \
            --menu "Select an NTP server to edit or remove, or add a new one." 0 0 0 \
            "${MENU[@]}" \
            "Add" "Add a new server" \
            "Save" "Save new NTP configuration" \
            2> "${DIALOG_RESULTFILE}"
        [ $? -eq 0 ] || return 1

        RESULT="`cat "${DIALOG_RESULTFILE}"`"
        case "${RESULT}" in
        Add)
            ntp_add_server
            ;;
        Save)
            ntp_save_config
            ;;
        *)
            ntp_edit_server "${RESULT}"
            ;;
        esac
    done

    assert "ntp_setup unreachable"
}



# vim: ts=4:sw=4:expandtab:syntax=sh
