#!/bin/bash

export PATH="${PATH}:/bin:/sbin:/usr/bin:/usr/sbin"

readonly AEMBIT_GROUP_NAME="aembit"
readonly AEMBIT_AGENT_PROXY_USER_NAME="aembit_agent_proxy"
readonly AEMBIT_AGENT_PROXY_SYSTEMD_UNIT="aembit_agent_proxy.service"
readonly AEMBIT_AGENT_PROXY_VERSION="1.9.1302"
readonly AEMBIT_AGENT_PROXY_INSTALL_DIR="/opt/aembit/edge/agent_proxy"
readonly AEMBIT_AGENT_PROXY_INSTALL_DIR_BIN="${AEMBIT_AGENT_PROXY_INSTALL_DIR}"/"${AEMBIT_AGENT_PROXY_VERSION}"/bin
readonly AEMBIT_AGENT_PROXY_INSTALL_DIR_SCRIPTS="${AEMBIT_AGENT_PROXY_INSTALL_DIR}"/"${AEMBIT_AGENT_PROXY_VERSION}"/scripts
readonly AEMBIT_AGENT_PROXY_JOURNALD_CONFIG_FILE="/etc/systemd/journald@aembit_agent_proxy.conf"
readonly AEMBIT_AGENT_PROXY_VERSION_PATTERN="[[:digit:]]*.[[:digit:]]*.[[:digit:]]*"

INSTALLER_DIR="$(dirname ${0})"
readonly LOG_FILE="${INSTALLER_DIR}"/installer.log

readonly SYSTEMD_UNIT_FILES_FOLDER="/etc/systemd/system"

log() {
    local level="${1}"
    shift

    local log_fmt="%s %s\n"
    if [ "${level}" ]; then
        log_fmt="%s ${level} %s\n"
    fi

    for line in "$@"; do
        printf "${log_fmt}" "$(date +"%H:%M:%S")" "${line}" | tee -a "${LOG_FILE}"
    done
}

log_info() {
    log "Info:" "$@"
}

log_warn() {
    log "Warning:" "$@"
}

log_err() {
    log "Error:" "$@"
}

check_for_required_env_var() {
    env_var_name=$1
    env_var_value="${!env_var_name}"

    if [ -z "${env_var_value}" ]; then
        log_err "Required environment variable \"${env_var_name}\" is not defined."
        exit 1
    fi
}

check_if_package_missing() {
    package=$1

    if ! which "${package}" > /dev/null 2>&1; then
        if [ -z "${missing_packages}" ]; then
            missing_packages="${package}"
        else
            missing_packages="${missing_packages}, ${package}"
        fi
    fi
}

check_required_dependencies() {
    log_info "Checking for required package dependencies."

    check_if_package_missing pgrep
    check_if_package_missing grep
    check_if_package_missing id
    check_if_package_missing getent
    check_if_package_missing useradd
    check_if_package_missing groupadd
    
    if [ -n "${missing_packages}" ]; then
        log_err "One or more necessary packages were missing. Please install the following package(s) and then rerun the installer: ${missing_packages}"
        exit 1
    fi
}

get_installed_versions() {
    local installed_versions
    if [ -d "${AEMBIT_AGENT_PROXY_INSTALL_DIR}" ]; then
        # Use find to locate files in the specified directory
        for file in ${AEMBIT_AGENT_PROXY_INSTALL_DIR}/${AEMBIT_AGENT_PROXY_VERSION_PATTERN}
        do
            # for empty dir it would return the pattern, check if the file exists
            if ! [ -e "${file}" ]; then
                return 1
            fi
            installed_versions="${installed_versions} $(basename "${file}")"
       done
    else
        return 1
    fi
    printf '%s' "${installed_versions}"
    return 0
}

check_for_existing_installation() {
    # TODO - upgrade behavior should be opt-in.
    # Check if there are process(es) running under AP user.
    if pgrep -u "${AEMBIT_AGENT_PROXY_USER_NAME}" &>/dev/null; then
        log_err "Aembit Agent Proxy process is already running. Please uninstall it first."
        exit 1
    fi

    if get_installed_versions; then
        log_err "An exisitng Aembit Agent Proxy installation was found. Please uninstall it first."
        exit 1
    fi
}

create_user_and_group() {
    if getent group "${AEMBIT_GROUP_NAME}" > /dev/null 2>&1; then
        log_info "Group \"${AEMBIT_GROUP_NAME}\" exists"
    else
        log_info "Group \"${AEMBIT_GROUP_NAME}\" does not exist. Creating."
        if groupadd "${AEMBIT_GROUP_NAME}"; then
            log_info "Group created"
        else
            log_err "Error creating the \"${AEMBIT_GROUP_NAME}\" group."
            exit 1
        fi
    fi

    if getent passwd "${AEMBIT_AGENT_PROXY_USER_NAME}" > /dev/null 2>&1; then
        log_info "User \"${AEMBIT_AGENT_PROXY_USER_NAME}\" exists"
    else
        log_info "User \"${AEMBIT_AGENT_PROXY_USER_NAME}\" does not exist. Creating."
        if useradd --no-create-home --shell /bin/false  -g "${AEMBIT_GROUP_NAME}" "${AEMBIT_AGENT_PROXY_USER_NAME}"; then
            log_info "User created"
        else
            log_err "There was an error creating the \"${AEMBIT_AGENT_PROXY_USER_NAME}\" user."
            exit 1
        fi
    fi
}

set_up_logs() {
    if ! cp "${INSTALLER_DIR}"/installer_components/journald@aembit_agent_proxy.conf "${AEMBIT_AGENT_PROXY_JOURNALD_CONFIG_FILE}"; then
        log_err "Unable to copy the journald configuration file to host."
        exit 1
    fi
}

copy_static_components_to_host() {
    if ! mkdir --parents "${AEMBIT_AGENT_PROXY_INSTALL_DIR_BIN}"; then
        log_err "Unable to make installation directory for Agent Proxy binary."
        exit 1
    fi

    if ! cp "${INSTALLER_DIR}"/aembit_agent_proxy "${AEMBIT_AGENT_PROXY_INSTALL_DIR_BIN}"/"${AEMBIT_AGENT_PROXY_BIN}"; then
        log_err "Unable to move the Agent Proxy binary to the installation directory."
        exit 1
    fi

    if ! mkdir --parents "${AEMBIT_AGENT_PROXY_INSTALL_DIR_SCRIPTS}"; then
        log_err "Unable to make installation directory for Agent Proxy scripts."
        exit 1
    fi

    if ! cp "${INSTALLER_DIR}"/installer_components/iptables_up.sh "${AEMBIT_AGENT_PROXY_INSTALL_DIR_SCRIPTS}"/iptables_up.sh; then
        log_err "Unable to move the iptables startup script to the installation directory."
        exit 1
    fi

    if ! cp "${INSTALLER_DIR}"/installer_components/iptables_down.sh "${AEMBIT_AGENT_PROXY_INSTALL_DIR_SCRIPTS}"/iptables_down.sh; then
        log_err "Unable to move the iptables shutdown script to the installation directory."
        exit 1
    fi

    if ! cp "${INSTALLER_DIR}"/uninstall "${AEMBIT_AGENT_PROXY_INSTALL_DIR_SCRIPTS}"/uninstall; then
        log_err "Unable to move the Agent Proxy uninstall script to the installation directory."
        exit 1
    fi
}

install_systemd_service() {
    if ! cp "${INSTALLER_DIR}"/installer_components/aembit_agent_proxy.service "${SYSTEMD_UNIT_FILES_FOLDER}"/"${AEMBIT_AGENT_PROXY_SYSTEMD_UNIT}"; then
        log_err "Unable to copy the systemd service file to the destination."
        exit 1
    fi

    if ! sed --in-place "s#{{ AGENT_CONTROLLER_LOCATION }}#${AEMBIT_AGENT_CONTROLLER}#" "${SYSTEMD_UNIT_FILES_FOLDER}"/"${AEMBIT_AGENT_PROXY_SYSTEMD_UNIT}"; then
        log_err "Unable to update the Agent Controller location in the systemd service file."
        exit 1
    fi

    if ! sed --in-place "s#{{ AGENT_CONTROLLER_LOCATION }}#${AEMBIT_AGENT_CONTROLLER}#" "${SYSTEMD_UNIT_FILES_FOLDER}"/"${AEMBIT_AGENT_PROXY_SYSTEMD_UNIT}"; then
        log_err "Unable to update the containers' CIDR block location in the systemd service file."
        exit 1
    fi

    if ! systemctl enable "${AEMBIT_AGENT_PROXY_SYSTEMD_UNIT}"; then
        log_err "Unable to enable the Agent Proxy systemd service."
        exit 1
    fi

    if ! systemctl start "${AEMBIT_AGENT_PROXY_SYSTEMD_UNIT}"; then
        log_err "Unable to start the Agent Proxy systemd service."
        exit 1
    fi
}

run_installer() {
    if [ "$(id --user)" -ne 0 ]; then
        log_err "Installer must be run as root."
        exit 1
    fi

    check_for_required_env_var AEMBIT_AGENT_CONTROLLER || exit 1
    if docker -v ; then
        check_for_required_env_var AEMBIT_DOCKER_CONTAINER_CIDR || exit 1
    fi

    check_required_dependencies || exit 1
    check_for_existing_installation || exit 1
    create_user_and_group || exit 1
    set_up_logs || exit 1
    copy_static_components_to_host || exit 1
    install_systemd_service || exit 1
}

main() {
    set -o pipefail
    log_info "Installing Aembit Agent Proxy"
    run_installer 2>&1
}

main || exit 1
