#! /usr/bin/env bash
########_ App list

# this is a reference template
# function _app_nosudo_template_function() {
# In function name `nosudo_` means, sudo isn't allowed, if replaced by
# `sudo_`, installtion will require sudo, or it can be `auto_`
# 
#     APP_TYPE=''       # bash-url, deb-github-release, deb-url
#     APP_ADDRESS=''    # bash-url:
#                       #     The complete URL to the installation bash script
#                       # deb-github-release:
#                       #     Owner/RepoName from the GitHub URL
#     APP_RELEASE=''    # Used by deb-github-release, default is 'latest'
# }
# this is a reference custom template
# function _app_template_function_custom() {
# }

function _app_sudo_gcm() {
# Installs GitCredentialManager from Microsoft
    APP_TYPE='deb-github-release'
    APP_ADDRESS='GitCredentialManager/git-credential-manager'
}

function _app_nosudo_homebrew() {
# Installs HomeBrew 
    APP_TYPE='bash-url'
    APP_ADDRESS='https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh'
}

function _app_sudo_gcloud_custom() {
    if [[ ! -r "/etc/apt/sources.list.d/packages.cloud.google.com" ]]; then
        eval $(error 1 \
            "Google Cloud Platform sources are not installed yet, please run 'pqb-add-apt-repo gcloud' first" \
        ) || exit $?
        exit 1
    fi

    apt install google-cloud-sdk-gke-gcloud-auth-plugin google-cloud-cli kubectl
}

function _app_sudo_systeroid_custom() {
    if [[ -n "$(type cargo 2>/dev/null)" ]]; then
        cargo install systeroid
        cargo install systeroid-tui
    else    
        DL_URL=$( \
            get-github-release.sh orhun/systeroid '' 'x86_64-unknown-linux-gnu.tar.gz' \
            | grep 'tar.gz$' \
        )
        DL_PATH=$(download_temp $DL_URL)
        DL_DIR=$(dirname $DL_PATH)
        echo "Extracting..."
        tar zxC "$DL_DIR" -f "$DL_PATH"
        SRC_DIR=$( \
            find "$DL_DIR" -mindepth 1 -maxdepth 1 -type d -not -name '.' \
            | head -1 \
        )
        echo "Installing into /usr/local/bin..."
        mv "$SRC_DIR/systeroid"* /usr/local/bin
        [[ -n "$DL_DIR" && "$DL_DIR" =~ "/tmp/tmp." ]] && rm -R "$DL_DIR/"
    fi  
}

function _apt_sudo_rstudio() {
    APP_TYPE='deb-url'
    APP_ADDRESS=$( \
        wget -qO- https://rstudio.com/products/rstudio/download/ \
        | grep -Eoi '<a [^>]+>' |  grep -Eo 'href="[^\"]+"' \
        | grep -Eo '(http|https)://download.*\.deb' \
        | grep 'jammy' \
    )
}

function _app_sudo_docker_system_custom() {
    if [[ ! -r "/etc/apt/sources.list.d/download.docker.com.list" ]]; then
        eval $(error 1 \
            "Docker sources are not installed yet, please run 'pqb-add-apt-repo docker' first" \
        ) || exit $?
        exit 1
    fi

    [[ -z "$(type -fP docker)" ]] \
        && echo "Installting docker-ce and related packages..." \
        && DEBIAN_FRONTEND=noninteractive apt-get install --yes docker-ce docker-ce-cli containerd.io docker-compose-plugin \
        && printf "\n\ndocker installed\n\n"
    CUR_USER=$USER
    [[ -n "$SUDO_USER" ]] \
        && CUR_USER=$SUDO_USER
    echo "Adding current user ($CUR_USER) to the 'docker' group..."
    usermod --groups docker          --append $CUR_USER

    if [[ ! -x /usr/local/bin/compose-switch ]]; then
        echo "Setting up docker-switch for docker-compose backward compatibility..."
        curl -fL https://raw.githubusercontent.com/docker/compose-switch/master/install_on_linux.sh | sh
        update-alternatives --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99
    fi
}

############ Script Logic starts here
set -e
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
USER_HOME=$HOME
[[ -n "${SUDO_USER}" ]] && USER_HOME="$(eval "echo ~${SUDO_USER}")"
. ${SHRC_D:-$USER_HOME/.pqb.shrc.d}/01_util.functions 

get_clean_path() {
  sed 's/ *:\?$//g;s/`/``/g;s/:/`:`/g;s/\\`:`/\\:/g;' <<< $1 | \
    awk -v RS='`:`' -v ORS='`:`' '!arr[$0]++' | \
    sed 's/`:`/:/g;s/:$//g'
}
#PATH=$( get_clean_path "${PATH}:${SCRIPT_DIR}" )
#echo $PATH

function download_temp() {
    local APP_ADDRESS=${1:-${APP_ADDRESS}}

    local DL_URL="${1}"
    local DL_FILENAME="${2:-${DL_URL##*/}}"
    local DL_DIR=$(mktemp -dt)
    pushd "$DL_DIR" > /dev/null || return $?
    # Download the .targz file
    echo "Downloading $DL_FILENAME to $DL_DIR..." 1>&2
    wget -q "$DL_URL" && [[ -n "$SUDO_USER" ]] && chown -R $SUDO_USER "$DL_DIR"
    popd > /dev/null || return $?
    
    printf "${DL_DIR}/${DL_FILENAME}"
}

function install_app_bash_url() {
    local APP_ADDRESS=${1:-${APP_ADDRESS}}

    /bin/bash -c "$(curl -fsSL ${APP_ADDRESS})"
}
function install_app_deb_url() {
    local APP_ADDRESS=${1:-${APP_ADDRESS}}

    install-deb-from-web.sh "${APP_ADDRESS}"
}
function install_app_deb_github_release() {
    local APP_PROJECT=${1:-${APP_ADDRESS}}
    local APP_RELEASE=${2:-${APP_RELEASE:-latest}}

    install_app_deb_url $( \
        get-github-release.sh "${APP_PROJECT}" "${APP_RELEASE}" \
    )
}

# The function that does the _Heavy Lifting_.
# see the code that follows for the parameter signature
function install_app() {

    local allFuncs=$( printf '%s\n' $(get_app_install_functions) $allFuncs | grep "_${1}\(_custom\)\?$" )
    local okFuncs=$allFuncs
    
    if [[ -n $okFuncs ]]; then
        if [[ $EUID -ne 0 ]]; then
            okFuncs=$(printf '%s\n' $okFuncs | grep -v "^sudo_")
        else
            okFuncs=$(printf '%s\n' $okFuncs | grep -v "^nosudo_")
        fi

        if [[ -n $okFuncs ]]; then
            okFuncs=$(printf '%s\n' $okFuncs | head -1)
            if [[ "$(type -t _app_${okFuncs})" != 'function' \
               &&  "$(type -t _app_${okFuncs}_custom)" != 'function' ]]; then
                unset okFuncs
            fi
        fi

        if [[ -n $okFuncs ]]; then
            if [[ "$okFuncs" =~ "${1}_custom" ]]; then
                eval "_app_$okFuncs"
                return $?
            else
                eval "_app_$okFuncs" || return $?

                printf "%s=%s\n" \
                    'APP_TYPE' "${APP_TYPE}" \
                    'APP_ADDRESS' "${APP_ADDRESS}" \
                    'APP_RELEASE' "${APP_RELEASE}"
                
               #echo \
                eval "install_app_$(echo ${APP_TYPE} | sed 's/-/_/g;')"
            fi
        else
            echo "Failed to launch $allFuncs"
            return 1
        fi
    else
        echo "Could not find installation instructions for ${1}"
        return 1
    fi
   
    echo "App $1 installed"
}

function get_app_install_functions() {
    typeset -f \
        | grep '^_app_' | sed 's/^_app_//; s/ () *$//;'
}

function usage() {
    printf "  %s\n" \
        "Usage:" \
        "  $0 [-v[v]] " \
        "         [--no-init] [--no-overwrite] " \
        "         all|<app name>[ <app name 2>...] " \
        "" \
        "Apps: $( \
          printf "\n      %s" $( \
            get_app_install_functions \
              | sed 's/_custom$//' \
              | sed 's/^\([^_]*sudo[^_]*\)_\(.*\)$/\2(\1)/' \
              | sort \
        ))" \
        "" \
        "Options:" \
        "  --no-init      - skip initialization." \
        "  -v[v]          - script verbosity, equivalent to set -x and set -xv" \
        ""
}

function main() {
    [[ ${#APP_LIST[@]} -eq 0 ]] && usage && return 1

    _OS=$(lsb_release -is | awk '{ print tolower($0) }')
    [[ $_OS == 'pop' ]] && _OS='ubuntu'
    _REL=$(lsb_release -rs) # Release
    _CNM=$(lsb_release -cs) # CodeName
    _ARC=$(dpkg --print-architecture) # Architecture

    ANSI_Cyan "Initializing: Installing basic packages..."; echo
    if [[ -n "$SHOULD_INIT" ]]; then
        # Make sure the /usr/share/keyrings dir exists
        mkdir -p /usr/share/keyrings 2>&1 > /dev/null

        # Make sure all of the basic required tools are installed for the code
        # below to work
        apt-get install --yes --no-install-recommends \
            curl gnupg software-properties-common apt-transport-https
    fi
    ANSI_Green "Done."; echo

    while read r; do
        ANSI_Cyan "Installing $r..."; echo
        install_app $r || return 2
        ANSI_Green "Installation of $r completed."; echo
    done < <(printf "%s\n" "${APP_LIST[@]}")

    [[ -z "${SUDO_USER}" ]] && exec $SHELL \
    || echo 'It is recommended that you restart your shell (exec $SHELL)'
}

# Iterate through stdin or parameters
if [[ $# == 0 ]]; then
    usage
else
    APP_LIST=()
    _SHOULD_INIT=1

    READCMD='printf "%s\n" "${@}"'
    [[ $# == 1 && $1 == '-' ]] && READCMD='cat - '
    while read a; do
        # Switch on _YES
        [[ "$a" == "-v" ]] && set -x && continue
        [[ "$a" == "-vv" ]] && set -xv && continue
        [[ "$a" == "--no-init" ]] && unset _SHOULD_INIT && continue

        # Add app
        [[ -n "$a" ]] && APP_LIST+=("$a")
    done < <( eval $READCMD )

    main
fi