#!/usr/bin/env bash
# NETINT (c) 2020
# This script is intended to help customers install Netint software and firmware

function end_script() {
    printf "\n"
    printf "Stopped t4xx_quick_installer.sh\n"
    trap - EXIT
    exit 0
}

# determine if host is "ubuntu", "centos", or "macos"
# put result in $get_os_ret
function get_os() {
    if lsb_release -i 2> /dev/null | grep -iq Ubuntu; then
        get_os_ret="ubuntu"
    elif lsb_release -i 2> /dev/null | grep -iq CentOS; then
        get_os_ret="centos"
    elif sw_vers -productName | grep -iq macOS; then
        get_os_ret="macos"
    else
        get_os_ret=""
        return 1
    fi
    return 0
}

# configure variables for terminal color text based on OS
function setup_terminal_colors() {
    if [[ $SHELL =~ .*zsh ]]; then
        cRst="\x1b[0m"
        cRed="\x1b[31m"
        cGrn="\x1b[32m"
        cYlw="\x1b[33m"
        cBlu="\x1b[34m"
        cMag="\x1b[35m"
        cCyn="\x1b[36m"
    else
        cRst="\e[0m"
        cRed="\e[31m"
        cGrn="\e[32m"
        cYlw="\e[33m"
        cBlu="\e[34m"
        cMag="\e[35m"
        cCyn="\e[36m"
    fi
}

function install_yasm() {

    rc=1
    curl -O http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz &&
    tar -zxf yasm-1.3.0.tar.gz && rm yasm-1.3.0.tar.gz && cd yasm-1.3.0/ &&
    ./configure && make && sudo make install && cd .. &&
    rm -rf yasm-1.3.0 &&
    rc=0
    return $rc
}

function install_os_prereqs() {
    rc=1
    if [[ "$get_os_ret" == "ubuntu" ]]; then
        echo -e "Installing OS pre-requisites for ${cYlw}Ubuntu${cRst}"
        echo "Installing pkg-config, git, and gcc"
        sudo apt-get install -y pkg-config git gcc &&
        echo "Installing YASM" &&
        install_yasm &&
        rc=0
        return $rc
    elif [[ "$get_os_ret" == "centos" ]]; then
        echo -e "Installing OS pre-requisites for ${cYlw}CentOS${cRst}"
        echo "Installing epel-release, pkg-config, git, redhat-lsb-core, make, and gcc"
        sudo yum --enablerepo=extras install -y epel-release &&
        sudo yum install -y pkgconfig git redhat-lsb-core make gcc &&
        echo "Installing YASM" &&
        install_yasm &&
        rc=0
        return $rc
    elif [[ "$get_os_ret" == "macos" ]]; then
        echo -e "Installing OS pre-requisites for ${cYlw}MacOS${cRst}"
        echo "Installing Xcode command line tools"
        xcode-select --install 2>&1 | tee xcode_install_log.txt
        rc=${PIPESTATUS[0]}
        if [ $rc -ne 0 ] && ! grep -q "command line tools are already installed" xcode_install_log.txt; then
            return $rc
        elif grep -q "install requested for command line developer tools" xcode_install_log.txt; then
            read -p "Complete command line tools install on GUI. Press [Y/y] to continue. " -n 1 -r
        fi
        rm xcode_install_log.txt

        if ! which pkg-config 2>&1 2> /dev/null; then
            echo "Installing pkgconfig" &&
            curl -O https://pkg-config.freedesktop.org/releases/pkg-config-0.28.tar.gz &&
            tar -zxvf pkg-config-0.28.tar.gz && rm pkg-config-0.28.tar.gz &&
            cd pkg-config-0.28 && export CC=/usr/bin/cc 2> /dev/null ||
            setenv CC /usr/bin/cc 2> /dev/null &&
            ./configure --prefix=/usr/local CC=$CC --with-internal-glib &&
            make && sudo make install && cd .. && rm -rf pkg-config-0.28 ||
            return 1
        fi

        yasm_ver=$(which yasm 2>&1 > /dev/null && yasm --version | \
                   egrep -o "[[:digit:]]\.[[:digit:]]\.[[:digit:]]")
        if [ -n $which ] && [[ $(printf "${yasm_ver}\n1.3.0\n" | sort -V | head -n 1) == "1.3.0" ]]; then
            return 0
        else
            echo "Installing YASM"
            install_yasm
            return $?
        fi
    else
        echo "Cannot determine OS for installation of pre-requisites"
        return 1
    fi
}

function install_libxcoder() {
    rc=1

    sudo rm -rf libxcoder_logan &> /dev/null
    cp -r release/libxcoder_logan ./ && cd libxcoder_logan && bash build.sh && cd .. && rc=0
    if [ $rc != 0 ]; then
        return $rc
    fi

    if [[ "$get_os_ret" == "ubuntu" ]] || [[ "$get_os_ret" == "centos" ]]; then
        sudo rm /dev/shm/NI_LOGAN_* &> /dev/null
        timeout -s KILL 5 init_rsrc_logan 2>&1 > /dev/null
    elif [[ "$get_os_ret" == "macos" ]] && [[ -f "/private/tmp/NI_LOGAN_LCK_CODERS" ]]; then
        echo "Cannot reset POSIX shared memory on MacOS via terminal."
        echo "You may need to reboot computer and run init_rsrc_logan"
        timeout -s KILL 5 init_rsrc_logan 2>&1 > /dev/null
    else
        timeout -s KILL 5 init_rsrc_logan 2>&1 > /dev/null
    fi
    rc=$?
    return $rc
}

# $1 - FFmpeg version to use (eg. 4.2.1)
function install_ffmpeg_ver() {
    rc=1

    echo "Installation Path: ./FFmpeg/"
    echo "Note: This will install NETINT-T4XX FFmpeg-${ver_num} patch ontop base ${ver_num} FFmpeg"
    echo "      Any customizations must be integrated manually"
    echo ""
    echo "Compile FFmpeg with --enable-static to statically link FFmpeg libraries, or with"
    echo "--enable-shared if intending to interface with libavcodec directly."
    echo -e "${cYlw}Choose an option:${cRst}"
    select opt in "Compile with --enable-static" "Compile with --enable-shared"; do
        case $opt in
            "Compile with --enable-static")
                extra_build_flag=""
                break
            ;;
            "Compile with --enable-shared")
                extra_build_flag=" --shared"
                if ls /usr/local/lib/libav*.so* /usr/local/lib/libswscale.so* \
                      /usr/local/lib/libswresample.so* /usr/local/lib/libpostproc.so* &> /dev/null; then
                    echo "Old libav*, libswscale, libswresample, libpostproc packages in "
                    echo "/usr/local/lib/ will interfere with new FFmpeg installed."

                    echo -e "${cYlw}Choose an option:${cRst}"
                    select opt in "Remove old FFmpeg libs" "Continue without removal" "Return to main menu"; do
                        case $opt in
                            "Remove old FFmpeg libs")
                                sudo rm /usr/local/lib/libav*.so* /usr/local/lib/libswscale.so* \
                                        /usr/local/lib/libswresample.so* /usr/local/lib/libpostproc.so*
                                break
                            ;;
                            "Continue without removal")
                                break
                            ;;
                            "Return to main menu")
                                return $rc
                            ;;
                            *) echo -e "${cRed}Invalid choice!${cRst}"
                            ;;
                        esac
                    done
                fi
                break
            ;;
            *) echo -e "${cRed}Invalid choice!${cRst}"
            ;;
        esac
    done

    echo "Downloading FFmpeg-${ver_num} from github..." &&
    sudo rm -rf FFmpeg/ &> /dev/null; mkdir FFmpeg/
    # Determine if target is a tag/branch name or commit SHA1. Download accordingly
    if  [[ `echo ${1} | grep -E "^[0-9a-fA-F]{7,}$"` != "" ]]; then
        git clone https://github.com/FFmpeg/FFmpeg.git FFmpeg/
        rc=$?; if [ $rc -ne 0 ]; then
            echo "Failed to git clone FFmpeg"
            return $rc
        fi
        cd FFmpeg/ && git checkout ${1} && cd ..
    else
        git clone -b ${1} --depth=1 https://github.com/FFmpeg/FFmpeg.git FFmpeg/
        rc=$?; if [ $rc -ne 0 ]; then
            echo "Failed to git clone FFmpeg"
            return $rc
        fi
    fi
    echo "Copying NETINT patch for FFmpeg-${ver_num} to installation directory..." &&
    cp release/FFmpeg-${ver_num}_t4[03xX][28xX]_patch FFmpeg/ &&
    cd FFmpeg/ &&
    patch -t -p 1 < FFmpeg-${ver_num}_t4[03xX][28xX]_patch &&
    echo "Compiling FFmpeg-${ver_num}..." &&
    sudo make clean &> /dev/null || true &&
    bash build_ffmpeg.sh --ffprobe${extra_build_flag} &&
    sudo make install &&
    chmod 755 run_ffmpeg_logan.sh &&
    cd .. &&
    rc=0
    sudo ldconfig 2> /dev/null
    return $rc
}

# $1 - rc
# $2 - prefix to print
function print_eval_rc() {
    if [[ $1 == 0 ]]; then
        echo -e "${cGrn}${2} ran succesfully${cRst}"
    else
        echo -e "${cRed}${2} failed${cRst}"
    fi
    return $1
}

trap end_script EXIT

if [ -n "$1" ]; then
    echo "No input args accepted."
    echo "There is a numbered menu after confirming tarballs to use."
    exit 0
fi

get_os
setup_terminal_colors

base_dir=$(pwd)
fw_pack=$(ls T4[03xX][28xX]_V*.*.*.tar.gz | sort -V | tail -n 1)
sw_pack=$(ls Codensity_T4[03xX][28xX]_Software_Release_V*.*.*.tar.gz | sort -V | tail -n 1)
fw_folder=$(echo ${fw_pack} | perl -nle'print $& while m{T4[03xX][28xX]_V[0-9A-Z\.]{5}(?=\.tar\.gz)}g')

export LD_LIBRARY_PATH=/usr/local/lib/
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/

echo "Welcome to the NETINT t4xx_quick_installer utility"
echo "Please put the FW and FFmpeg release package you wish to install in the same directory as this script"
echo -e "The latest FW release package found here is:     ${cYlw}${fw_pack}${cRst}"
echo -e "The latest FFmpeg release package found here is: ${cYlw}${sw_pack}${cRst}"

fw_pack_ver=`echo ${fw_pack} | perl -nle'print $& while m{(?<=T4[03xX][28xX]_V)\w\.\w\.\w.*(?=.tar.gz)}g'`
sw_pack_ver=`echo ${sw_pack} | perl -nle'print $& while m{(?<=Codensity_T4[03xX][28xX]_Software_Release_V)\w\.\w\.\w.*(?=.tar.gz)}g'`
if [[ "$fw_pack_ver" != "$sw_pack_ver" ]]; then
    echo -e "${cRed}WARNING${cRst}: FW and SW versions do not match each other"
fi
read -p "Press [Y/y] to confirm the use of these two release packages. " -n 1 -r
echo ""
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "Please remove release package files you do not wish to use and try again."
    end_script
fi

# Extract SW release package for auto discovery of FFmpeg versions
echo "Removing old './release/' folder..."
sudo rm -rf release
echo "Extracting new FW & SW release folders"
tar -zxf $fw_pack
tar -zxf $sw_pack

# Setup options table
options=("Setup Environment variables"
         "Unlock CPU governor"
         "Install OS prerequisite packages"
         "Install NVMe CLI"
         "Install Libxcoder")

for ff_patch in release/FFmpeg-*_t4xx_patch; do
    ver_num=$(echo ${ff_patch} | perl -nle'print $& while m{release/FFmpeg-\K[^_]*(?=_t4xx_patch)}g')
    if [[ $ver_num == '*' ]]; then
        continue;
    fi
    options+=("Install FFmpeg-${ver_num}")
done

options+=("Firmware Update"
          "Quit")

# Main menu loop
COLUMNS=20
while true; do
    cd $base_dir
    echo -e "${cYlw}Choose an option:${cRst}"
    select opt in "${options[@]}"; do
        case $opt in
            "Setup Environment variables")
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                if [[ "$get_os_ret" == "macos" ]]; then
                    echo -e "Environment variables setup ${cRed}not supported/unnecessary${cRst} on MacOS"
                    print_eval_rc $? "${opt}"
                    break
                fi

                sudo grep -qxF 'Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin' /etc/sudoers ||
                sudo `which sed` -i '/^Defaults    secure_path = /s/$/:\/usr\/local\/sbin:\/usr\/local\/bin/' /etc/sudoers &&
                sudo grep -qxF 'Defaults    env_keep += "PKG_CONFIG_PATH"' /etc/sudoers ||
                sudo sh -c "echo 'Defaults    env_keep += \"PKG_CONFIG_PATH\"' >> /etc/sudoers"

                export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/ &&
                export LD_LIBRARY_PATH=/usr/local/lib/ &&
                sudo grep -qxF '/usr/local/lib' /etc/ld.so.conf ||
                sudo sh -c 'echo "/usr/local/lib" >> /etc/ld.so.conf'
                sudo ldconfig

                print_eval_rc $? "${opt}"
                break
            ;;
            "Unlock CPU governor")
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                if [[ "$get_os_ret" == "macos" ]]; then
                    echo -e "CPU govenor unlock ${cRed}not supported/unnecessary${cRst} on MacOS"
                    print_eval_rc $? "${opt}"
                    break
                fi

                grep -qxF 'for (( i=0; i<`nproc`; i++ )); do sudo sh -c "echo performance > /sys/devices/system/cpu/cpu${i}/cpufreq/scaling_governor"; done 2> /dev/null' ~/.bashrc ||
                echo 'for (( i=0; i<`nproc`; i++ )); do sudo sh -c "echo performance > /sys/devices/system/cpu/cpu${i}/cpufreq/scaling_governor"; done 2> /dev/null' >> ~/.bashrc
                print_eval_rc $? "${opt}"
                break
            ;;
            "Install OS prerequisite packages")
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                install_os_prereqs
                print_eval_rc $? "${opt}"
                break
            ;;
            "Install NVMe CLI")
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                if [[ "$get_os_ret" == "macos" ]]; then
                    echo -e "NVMe CLI ${cRed}not supported${cRst} on MacOS"
                    print_eval_rc $? "${opt}"
                    break
                fi
                nvme_cli_ver="1.6"
                if [[ $(gcc -dumpversion | grep -Poh "^\d+") -ge 11 ]]; then
                    nvme_cli_ver="1.16"
                fi
                wget https://github.com/linux-nvme/nvme-cli/archive/v${nvme_cli_ver}.tar.gz &&
                tar -zxf v${nvme_cli_ver}.tar.gz && cd nvme-cli-*/ && sudo make && sudo make install && cd ..
                print_eval_rc $? "${opt}"
                break
            ;;
            "Install Libxcoder")
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                install_libxcoder
                print_eval_rc $? "Libxcoder installation"
                break
            ;;
            Install\ FFmpeg-*)
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                # get FFmpeg version number from $opt
                ver_num=$(echo ${opt} | perl -nle'print $& while m{Install FFmpeg-\K.*}g')
                install_ffmpeg_ver $ver_num
                print_eval_rc $? "FFmpeg installation"
                break
            ;;
            "Firmware Update")
                echo -e "${cYlw}You chose $REPLY which is $opt${cRst}"
                if [[ "$get_os_ret" == "macos" ]]; then
                    echo -e "FW update ${cRed}not supported${cRst} on MacOS"
                    print_eval_rc $? "${opt}"
                    break
                fi
                cd ${fw_folder} && ./t4xx_auto_upgrade.sh &&
                cd .. &&
                echo "re"
                print_eval_rc $? "${opt}"
                break
            ;;
            "Quit")
                exit
            ;;
            *) echo -e "${cRed}Invalid choice!${cRst}"
            ;;
        esac
    done
done
