#!/usr/bin/env bash

# TODO: update based off latest changes in rtpengine/debian/install.sh

# Debug this script if in debug mode
(( $DEBUG == 1 )) && set -x

# Import dsip_lib utility / shared functions if not already
if [[ "$DSIP_LIB_IMPORTED" != "1" ]]; then
    . ${DSIP_PROJECT_DIR}/dsiprouter/dsip_lib.sh
fi

function debSearch() {
    local DEB_SEARCH="$1" SEARCH_URL

    # search security.ubuntu.com for package
    SEARCH_URL="http://security.ubuntu.com/ubuntu/pool/main/l/linux/${DEB_SEARCH}.deb"
    if [[ $(curl -sL -I -w "%{http_code}" "$SEARCH_URL" -o /dev/null) == "200" ]]; then
        echo "$SEARCH_URL"
        return 0
    fi

    # search archive.ubuntu.com for package
    SEARCH_URL="http://archive.ubuntu.com/ubuntu/pool/main/l/linux/${DEB_SEARCH}.deb"
    if [[ $(curl -sL -I -w "%{http_code}" "$SEARCH_URL" -o /dev/null) == "200" ]]; then
        echo "$SEARCH_URL"
        return 0
    fi

    # nowhere else we trust to search
    return 1
}

function aptInstallKernelHeadersFromURI() {
    local RET=0
    local KERN_HDR_URI="$1" KERN_HDR_DEB=$(basename "$1")
    local KERN_HDR_COMMON_URI="" KERN_HDR_COMMON_DEB=""

    (
        # download the .deb file
        cd /tmp/
        curl -sLO --retry 3 "$KERN_HDR_URI"

        # install dependent common headers
        KERN_HDR_COMMON_URI=$(
            debSearch $(
                dpkg --info "$KERN_HDR_DEB" 2>/dev/null |
                grep 'Depends:' |
                cut -d ':' -f 2 |
                tr ',' '\n' |
                grep -oP 'linux-headers-.*-common'
            )
        ) &&
        KERN_HDR_COMMON_DEB=$(basename "$KERN_HDR_COMMON_URI") &&
        curl -sLO --retry 3 "$KERN_HDR_COMMON_URI" && {
            apt-get install -y ./${KERN_HDR_COMMON_DEB}
            RET=$((RET + $?))
            apt-get install -y -f
            rm -f "$KERN_HDR_COMMON_DEB"
        }

        # install the kernel headers
        apt-get install -y ./${KERN_HDR_DEB}
        RET=$((RET + $?))
        rm -f "$KERN_HDR_DEB"
        exit $RET
    )

    return $?
}

# prints $1 if not virtual or the package that provides $1 if virtual
function resolveAptVirtualPkg() {
    apt-cache search "^$1\$" | awk '{print $1}'
}

# when run from root of a debian repo finds the package dependencies
function getDebDependencies() {
    local TMP DISCRETE_PKGS CONDITIONAL_PKGS RESULT_PKGS=()

    TMP=$(
        dpkg-checkbuilddeps 2>&1 |
        awk -F 'Unmet build dependencies: ' '{print $2}' |
        perl -pe 's% \(.*?\)%%g'
    )
    DISCRETE_PKGS=$(perl -pe 's%[^ ]+ \| [^ ]+%%g' <<<"$TMP")
    CONDITIONAL_PKGS=$(
        grep -oP '[^ ]+ \| [^ ]+' <<<"$TMP" | (
            while IFS= read -r LINE; do
                PKG=$(resolveAptVirtualPkg $(awk -F ' | ' '{print $1}' <<<"$LINE"))
                if [[ -n "$(apt-cache search $PKG 2>/dev/null)" ]]; then
                    echo "$PKG"
                else
                    PKG=$(resolveAptVirtualPkg $(awk -F ' | ' '{print $2}' <<<"$LINE"))
                    [[ -n "$(apt-cache search $PKG 2>/dev/null)" ]] && echo "$PKG"
                fi
            done
        )
    )

    for PKG in $DISCRETE_PKGS; do
        RESULT_PKGS+=( $(resolveAptVirtualPkg "$PKG") )
    done
    for PKG in $CONDITIONAL_PKGS; do
        RESULT_PKGS+=( "$PKG" )
    done

    echo ${RESULT_PKGS[@]}
}

function install {
    local MISSING_PKGS
    local NPROC=$(nproc)

    # Install required packages and remove conflicting packages
    { dpkg -l ufw &>/dev/null && apt-get remove -y ufw || :; } &&
    apt-get install -y git perl logrotate rsyslog firewalld dpkg-dev

    if (( $? != 0 )); then
        printerr "Problem with installing the required libraries for RTPEngine"
        return 1
    fi

    # try installing kernel dev headers in the following order:
    # 1: headers from security.ubuntu.com
    # 2: headers from archive.ubuntu.com
    # NOTE: headers should be installed for all kernels on the system
    #       but we do not want to support ancient kernel dependencies
    (
        RET=0
        for OS_KERNEL in $(ls /lib/modules/ 2>/dev/null); do
            apt-get install -y linux-headers-${OS_KERNEL} ||
            aptInstallKernelHeadersFromURI $(debSearch linux-headers-${OS_KERNEL})
            RET=$((RET+$?))
        done
        exit $RET
    )

    # require kernel module
    if (( $? != 0 )); then
        printerr "Problems occurred installing one or more kernel headers"
        return 1
    fi

    ## compile and install RTPEngine as a DEB package
    ## reuse repo if it exists and matches version we want to install
    if [[ -d ${SRC_DIR}/rtpengine ]]; then
        if [[ "$(getGitTagFromShallowRepo ${SRC_DIR}/rtpengine)" != "${RTPENGINE_VER}" ]]; then
            rm -rf ${SRC_DIR}/rtpengine
            git clone --depth 1 -c advice.detachedHead=false -b ${RTPENGINE_VER} https://github.com/sipwise/rtpengine.git ${SRC_DIR}/rtpengine
        fi
    else
        git clone --depth 1 -c advice.detachedHead=false -b ${RTPENGINE_VER} https://github.com/sipwise/rtpengine.git ${SRC_DIR}/rtpengine
    fi

    # apply our patches
    (
        cd ${SRC_DIR}/rtpengine &&
        patch -p1 -N <${DSIP_PROJECT_DIR}/rtpengine/deb-${RTPENGINE_VER}.patch
    )
    if (( $? > 1 )); then
        printerr 'Failed patching RTPEngine files prior to build'
        return 1
    fi

    # build and install using dpkg
    (
        cd ${SRC_DIR}/rtpengine

        # install all missing dependencies from the control file
        MISSING_PKGS=$(getDebDependencies)
        [[ -n "$MISSING_PKGS" ]] && apt-get install -y $MISSING_PKGS

        dpkg-buildpackage -us -uc -sa --jobs=$NPROC || exit 1

        systemctl mask ngcp-rtpengine-daemon.service

        apt-get install -y ../ngcp-rtpengine-daemon_*${RTPENGINE_VER}*.deb ../ngcp-rtpengine-iptables_*${RTPENGINE_VER}*.deb \
            ../ngcp-rtpengine-kernel-dkms_*${RTPENGINE_VER}*.deb ../ngcp-rtpengine-utils_*${RTPENGINE_VER}*.deb || exit 1

        systemctl unmask ngcp-rtpengine-daemon.service
        systemctl disable ngcp-rtpengine-daemon.service

        exit 0
    )

    if (( $? != 0 )); then
        printerr "Problem installing RTPEngine DEB's"
        return 1
    fi

    # ensure config dirs exist
    mkdir -p /run/rtpengine ${SYSTEM_RTPENGINE_CONFIG_DIR}
    chown -R rtpengine:rtpengine /run/rtpengine

    # allow root to fix permissions before starting services (required to work with SELinux enabled)
    usermod -a -G rtpengine root

    # setup rtpengine defaults file
    cp -f ${DSIP_PROJECT_DIR}/rtpengine/configs/default.conf /etc/default/rtpengine.conf

    # Enable and start firewalld if not already running
    systemctl enable firewalld
    systemctl start firewalld

    # Setup Firewall rules for RTPEngine
    firewall-cmd --zone=public --add-port=${RTP_PORT_MIN}-${RTP_PORT_MAX}/udp --permanent
    firewall-cmd --reload

    # Setup RTPEngine Logging
    cp -f ${DSIP_PROJECT_DIR}/resources/syslog/rtpengine.conf /etc/rsyslog.d/rtpengine.conf
    touch /var/log/rtpengine.log
    systemctl restart rsyslog

    # Setup logrotate
    cp -f ${DSIP_PROJECT_DIR}/resources/logrotate/rtpengine /etc/logrotate.d/rtpengine

    # Setup tmp files
    echo "d /var/run/rtpengine.pid  0755 rtpengine rtpengine - -" > /etc/tmpfiles.d/rtpengine.conf

   # Reconfigure systemd service files
    rm -f /lib/systemd/system/rtpengine*.service
    cp -f ${DSIP_PROJECT_DIR}/rtpengine/systemd/rtpengine-v3.service /lib/systemd/system/rtpengine.service
    chmod 644 /lib/systemd/system/rtpengine.service
    systemctl daemon-reload
    systemctl enable rtpengine

    # Reload systemd configs
    systemctl daemon-reload
    # Enable the RTPEngine to start during boot
    systemctl enable rtpengine

    # preliminary check that rtpengine actually installed
    if cmdExists rtpengine; then
        return 0
    else
        return 1
    fi
}

# Remove RTPEngine
function uninstall {
    systemctl stop rtpengine
    systemctl disable rtpengine
    rm -f /{etc,lib}/systemd/system/rtpengine.service 2>/dev/null
    systemctl daemon-reload

    apt-get remove -y ngcp-rtpengine\*

 rm -f /usr/sbin/rtpengine* /usr/bin/rtpengine /etc/rsyslog.d/rtpengine.conf /etc/logrotate.d/rtpengine

    # remove our firewall changes
    firewall-cmd --zone=public --remove-port=${RTP_PORT_MIN}-${RTP_PORT_MAX}/udp --permanent
    firewall-cmd --reload

    return 0
}

case "$1" in
    install)
        install && exit 0 || exit 1
        ;;
    uninstall)
        uninstall && exit 0 || exit 1
        ;;
    *)
        printerr "Usage: $0 [install | uninstall]"
        exit 1
        ;;
esac
