#!/bin/sh
PRODUCT_INFO=appmanager
PACKAGE_NAME=AppManagerDataExporter

SCRIPT_DIR="$(dirname "$0")"
ENV_FILE="service.env"
SERVICE_NAME="${PACKAGE_NAME}"

. "${SCRIPT_DIR}/${ENV_FILE}"

PrintToTerminal() {
    echo "$@"
}

CheckFlags() {
    for arg in "$@"; do

        if [ "$arg" = $ROOT_USER ]; then
            USER_TYPE=$ROOT_USER
        fi

        if [ "$arg" = $NOT_ROOT_USER ]; then
            USER_TYPE=$NOT_ROOT_USER
        fi

        if [ "$arg" = $AS_SERVICE ]; then
            SERVICE_REGISTRATION=$AS_SERVICE
        fi

        if [ "$arg" = $NOT_AS_SERVICE ]; then
            SERVICE_REGISTRATION=$NOT_AS_SERVICE
        fi

    done
}

CheckUser() {
    if [ "$(id -u)" -ne 0 ]; then
        echo "Error: This script must be executed with sudo or as root."
        exit 1
    fi
}

RegisterAsSystemctlService() {
    PrintToTerminal "Action: Registering as systemctl service"

    SERVICE_TYPE=${SYSTEMCTL}
    # Update service.env file with service type
    sed -i -e "/.*SERVICE_TYPE=.*/{s/.*SERVICE_TYPE=.*/SERVICE_TYPE=\"${SERVICE_TYPE}\"/}" "${SCRIPT_DIR}/service.env"

    cp "${SCRIPT_DIR}/${PACKAGE_NAME}.service" "/etc/systemd/system/${PACKAGE_NAME}.service"
    systemctl enable "${PACKAGE_NAME}.service"
    systemctl daemon-reload

    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        PrintToTerminal "Info: Registered as systemctl service"
        return 0
    else
        PrintToTerminal "Info: Failed to register as systemctl service"
        return 1
    fi
}

DeregisterAsSystemctlService() {
    PrintToTerminal "Action: Deregistering as systemctl service"

    SERVICE_TYPE=${NONE}
    # Update service.env file with service type
    sed -i -e "/.*SERVICE_TYPE=.*/{s/.*SERVICE_TYPE=.*/SERVICE_TYPE=\"${SERVICE_TYPE}\"/}" "${SCRIPT_DIR}/service.env"

    systemctl disable "${PACKAGE_NAME}.service"
    systemctl daemon-reload
    rm /etc/systemd/system/"${PACKAGE_NAME}.service"

    PrintToTerminal "Info: Deregistered as systemctl service"
}

RegisterAsInitdService() {
    PrintToTerminal "Action: Registering as init.d service"

    SERVICE_TYPE=${INITD}
    # Update service.env file with service type
    sed -i -e "/.*SERVICE_TYPE=.*/{s/.*SERVICE_TYPE=.*/SERVICE_TYPE=\"${SERVICE_TYPE}\"/}" "${SCRIPT_DIR}/service.env"

    cp "${SCRIPT_DIR}/${PACKAGE_NAME}.sh" "/etc/init.d/${PACKAGE_NAME}"
    chmod +x "/etc/init.d/${PACKAGE_NAME}"
    update-rc.d ${PACKAGE_NAME} defaults

    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        PrintToTerminal "Info: Registered as init.d service"
        return 0
    else
        PrintToTerminal "Info: Failed to register as init.d service"
        return 1
    fi
}

DeregisterAsInitdService() {
    PrintToTerminal "Action: Deregistering as init.d service"

    SERVICE_TYPE=${NONE}
    # Update service.env file with service type
    sed -i -e "/.*SERVICE_TYPE=.*/{s/.*SERVICE_TYPE=.*/SERVICE_TYPE=\"${SERVICE_TYPE}\"/}" "${SCRIPT_DIR}/service.env"

    update-rc.d -f ${PACKAGE_NAME} remove
    rm "/etc/init.d/${PACKAGE_NAME}"

    PrintToTerminal "Info: Deregistered as init.d service"
}

CheckAndRegister() {
    PrintToTerminal "Action: Checking service type"

    which systemctl >>/dev/null
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        PrintToTerminal "Info: systemctl available"
        RegisterAsSystemctlService
        return $?
    fi

    which update-rc.d >>/dev/null
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        PrintToTerminal "Info: init.d available"
        RegisterAsInitdService
        return $?
    fi
}

CheckAndDeregister() {
    PrintToTerminal "Action: Checking service type"

    which systemctl >>/dev/null
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        PrintToTerminal "Info: systemctl available"
        DeregisterAsSystemctlService
        return $?
    fi

    which update-rc.d >>/dev/null
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        PrintToTerminal "Info: init.d available"
        DeregisterAsInitdService
        return $?
    fi
}

SetPresets() {
    if [ $USER_TYPE = $ROOT_USER ]; then
        # Modify .sh script
        sed -i -e "/.*USER_TYPE=.*/{s/.*USER_TYPE=.*/USER_TYPE=\"${ROOT_USER}\"/}" "${SCRIPT_DIR}/service.env"
        # Modify .service script
        sed -i 's/^\(User=\)/#&/' "${SCRIPT_DIR}/${PACKAGE_NAME}.service"
    else
        # Modify .sh script
        sed -i -e "/.*USER_TYPE=.*/{s/.*USER_TYPE=.*/USER_TYPE=\"${NOT_ROOT_USER}\"/}" "${SCRIPT_DIR}/service.env"
        # Modify .service script
        sed -i 's/^\(#User=\)/User=/' "${SCRIPT_DIR}/${PACKAGE_NAME}.service"
    fi

    if [ $SERVICE_REGISTRATION = $NOT_AS_SERVICE ]; then
        CheckAndDeregister
        # Modify .sh script
        sed -i -e "/.*SERVICE_REGISTRATION=.*/{s/.*SERVICE_REGISTRATION=.*/SERVICE_REGISTRATION=\"${NOT_AS_SERVICE}\"/}" "${SCRIPT_DIR}/service.env"
    else
        CheckAndRegister
        # Modify .sh script
        sed -i -e "/.*SERVICE_REGISTRATION=.*/{s/.*SERVICE_REGISTRATION=.*/SERVICE_REGISTRATION=\"${AS_SERVICE}\"/}" "${SCRIPT_DIR}/service.env"
    fi
}

CreateUser() {
    useradd "${PRODUCT_INFO}-user" || PrintToTerminal "Info: User already exists."
}

GrantPermission() {
    chmod 777 "${SCRIPT_DIR}/../../${PACKAGE_NAME}" -R
}

install() {
    PrintToTerminal "Action: Installing $SERVICE_NAME"

    GrantPermission
    
    stop
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then

        CheckFlags "$@"
        SetPresets

        if [ "$USER_TYPE" = $NOT_ROOT_USER ]; then
            CreateUser
            su "${PRODUCT_INFO}-user" -c "${SCRIPT_DIR}/${SERVICE_NAME} $*"
        else
            "${SCRIPT_DIR}/${SERVICE_NAME}" "$@"
        fi
        start
        return $?
    else
        PrintToTerminal "Info: Installation failed, Unable to stop ${SERVICE_NAME}"
        return 0
    fi
}

configure() {
    PrintToTerminal "Action: Configuring $SERVICE_NAME"

    stop
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        su "${PRODUCT_INFO}-user" -c "${SCRIPT_DIR}/${SERVICE_NAME} $*"
        start
        return $?
    else
        PrintToTerminal "Info: Configuring failed, Unable to stop ${SERVICE_NAME}"
        return 1
    fi
}

uninstall() {
    PrintToTerminal "Action: Uninstalling $SERVICE_NAME"

    stop
    cmdstatus=$?
    if [ "$cmdstatus" -eq 0 ]; then
        CheckAndDeregister
        "${SCRIPT_DIR}/${SERVICE_NAME}" "$@" &
    else
        PrintToTerminal "Info: Uninstallation failed, Unable to stop ${SERVICE_NAME}"
        return 1
    fi
}

service_start() {
    service_status
    cmdstatus=$?
    if [ $cmdstatus -ne 0 ]; then
        "${SCRIPT_DIR}/${SERVICE_NAME}" &
        sleep 5
    fi
}

start() {
    PrintToTerminal "Action: Starting $SERVICE_NAME"

    if [ "$SERVICE_TYPE" = "$SYSTEMCTL" ]; then
        systemctl start "${PACKAGE_NAME}.service"
    elif [ "$SERVICE_TYPE" = "$INITD" ]; then
        /etc/init.d/${PACKAGE_NAME} start
    else
        if [ $USER_TYPE = $NOT_ROOT_USER ]; then
            su "${PRODUCT_INFO}-user" -c "${SCRIPT_DIR}/service.sh service_start -q"
        else
            service_start
        fi
    fi

    service_status
    cmdstatus=$?
    if [ $cmdstatus -eq 0 ]; then
        PrintToTerminal "Info: $SERVICE_NAME started successfully"
        return 0
    else
        PrintToTerminal "Info: Unable to start $SERVICE_NAME"
        return 1
    fi
}

service_stop() {
    PIDS=$(pgrep -f "${SCRIPT_DIR}/${SERVICE_NAME}")
    for ID in $PIDS; do
        kill "$ID"
        cmdstatus=$?
        if [ "$cmdstatus" -eq 0 ]; then
            PrintToTerminal "Info: $SERVICE_NAME ($ID) stopped"
        else
            PrintToTerminal "Info: Cannot stop $SERVICE_NAME ($ID)"
        fi
    done

    sleep 5

}

stop() {
    PrintToTerminal "Action: Stopping $SERVICE_NAME"

    if [ "$SERVICE_TYPE" = "$SYSTEMCTL" ]; then
        systemctl stop "${PACKAGE_NAME}.service"
    elif [ "$SERVICE_TYPE" = "$INITD" ]; then
        /etc/init.d/${PACKAGE_NAME} stop
    else
        if [ $USER_TYPE = $NOT_ROOT_USER ]; then
            su "${PRODUCT_INFO}-user" -c "${SCRIPT_DIR}/service.sh service_stop -q"
        else
            service_stop
        fi
    fi

    service_status
    cmdstatus=$?
    if [ $cmdstatus -eq 0 ]; then
        PrintToTerminal "Info: Unable to stop $SERVICE_NAME"
        PrintToTerminal "Info: Trying again using 'quit' command"
        return 1
    else
        PrintToTerminal "Info: $SERVICE_NAME stopped successfully"
        return 0
    fi
}

service_restart() {

    stop

    start

}

restart() {
    PrintToTerminal "Action: Restarting $SERVICE_NAME"

    if [ "$SERVICE_TYPE" = "$SYSTEMCTL" ]; then
        systemctl restart "${PACKAGE_NAME}.service"
        return $?
    elif [ "$SERVICE_TYPE" = "$INITD" ]; then
        /etc/init.d/${PACKAGE_NAME} restart
        return $?
    else
        service_restart
    fi
}

service_status() {
    if pgrep -f "${SCRIPT_DIR}/${SERVICE_NAME}" >/dev/null; then
        PrintToTerminal "Status: $SERVICE_NAME is in running state"
        return 0
    else
        PrintToTerminal "Status: $SERVICE_NAME is in stopped state"
        return 1
    fi
}

status() {
    PrintToTerminal "Action: Checking $SERVICE_NAME status"
    if [ "$SERVICE_TYPE" = "$SYSTEMCTL" ]; then
        systemctl status "${PACKAGE_NAME}.service"
        return $?
    elif [ "$SERVICE_TYPE" = "$INITD" ]; then
        /etc/init.d/${PACKAGE_NAME} status
        return $?
    else
        service_status
        return $?
    fi
}

health() {
    while :; do
        status
        cmdstatus=$?
        if [ "$cmdstatus" -eq 0 ]; then
            PIDS=$(pgrep -f "${SCRIPT_DIR}/${SERVICE_NAME}")
            for ID in $PIDS; do
                PrintToTerminal "Info: $SERVICE_NAME PID($ID)"
            done
            sleep 15
        else
            PrintToTerminal "Status: $SERVICE_NAME is in stopped state"
            exit 1
        fi
    done
}

version() {
    cat "${SCRIPT_DIR}/version"
}

run() {
    #run command runs the service as the current user, so grant permission to the current user
    #this command can be called without running the install command
    #this will not register the service, hence will not show up in systemctl or init.d

    PrintToTerminal "Action: Running $SERVICE_NAME"

    service_status
    cmdstatus=$?
    if [ $cmdstatus -ne 0 ]; then
        "${SCRIPT_DIR}/${SERVICE_NAME}" "$@" &
        sleep 5
    else
        PrintToTerminal "Info: $SERVICE_NAME is already running"
        return 0
    fi

    service_status
    cmdstatus=$?
    if [ $cmdstatus -eq 0 ]; then
        PrintToTerminal "Info: $SERVICE_NAME started successfully"
        return 0
    else
        PrintToTerminal "Info: Unable to start $SERVICE_NAME"
        return 1
    fi
}

quit() {
    #quit command stops the service as the current user

    PrintToTerminal "Action: Quitting $SERVICE_NAME"

    service_status
    cmdstatus=$?
    if [ $cmdstatus -eq 0 ]; then
        service_stop
    else
        PrintToTerminal "Info: $SERVICE_NAME is already stopped"
        return 0
    fi

    service_status
    cmdstatus=$?
    if [ $cmdstatus -eq 0 ]; then
        PrintToTerminal "Info: Unable to stop $SERVICE_NAME"
        return 1
    else
        PrintToTerminal "Info: $SERVICE_NAME stopped successfully"
        return 0
    fi
}

#script starts here

case "${1}" in
start)
    CheckUser
    start
    ;;
stop)
    CheckUser
    stop
    ;;
restart)
    CheckUser
    restart
    ;;
status)
    CheckUser
    status
    ;;
health)
    CheckUser
    health
    ;;
run)
    run "$@"
    ;;
quit)
    quit
    ;;
install)
    CheckUser
    install "$@"
    ;;
configure)
    CheckUser
    configure "$@"
    ;;
uninstall)
    CheckUser
    uninstall "$@"
    ;;
service_start)
    service_start
    ;;
service_stop)
    service_stop
    ;;
service_restart)
    service_restart
    ;;
service_status)
    service_status
    ;;
version)
    version
    ;;
*)
    PrintToTerminal "Operation [${1}] not supported"
    exit 1
    ;;
esac
