#!/bin/bash
# -----------------------------------------------------------------------------
# Helper Upgrade Script
# -----------------------------------------------------------------------------
# This script upgrades the Helper to the latest version. It should be run with
# the appropriate permissions.
#
# Created on: Fri Aug 18, 2023
# Last modified: Mon May 20, 2024
# Version: 1.0.2
#
# Copyright (c) 2022 ServBay, LLC.
# Author: Sam Wu (sam@servbay.dev)
# -----------------------------------------------------------------------------

SERVBAY_FOLDER="/Applications/ServBay.app"
HELPER_SRC_FOLDER="${SERVBAY_FOLDER}/Contents/Library/LaunchServices"

SRC_HELPER="${HELPER_SRC_FOLDER}/Dev.ServBay.macOS.ServBay.Helper"
SRC_HELPER_PLIST="${HELPER_SRC_FOLDER}/launchd.plist"

DIST_HELPER="/Library/PrivilegedHelperTools/Dev.ServBay.macOS.ServBay.Helper"
DIST_HELPER_PLIST="/Library/LaunchDaemons/Dev.ServBay.macOS.ServBay.Helper.plist"
BACKUP_HELPER="${DIST_HELPER}.bak"

MAX_RETRIES=3
RETRY_DELAY=2

if [[ $EUID -ne 0 ]]; then
    echo "This script requires root, exiting..."
    exit 1
fi

if [[ ! -f ${SRC_HELPER} || ! -f ${SRC_HELPER_PLIST} ]]; then
    echo "Source Helper not exists, exiting..."
    exit 1
fi

# Backup existing Helper
if [[ -f ${DIST_HELPER} ]]; then
    /bin/cp -f "${DIST_HELPER}" "${BACKUP_HELPER}"
fi

# Function to get current PID of Helper
get_helper_pid() {
    /bin/launchctl list | grep "Dev.ServBay.macOS.ServBay.Helper" | awk '{print $1}'
}

# Get current PID
current_pid=$(get_helper_pid)
echo "Current PID: $current_pid"

# Copy new Helper
/bin/cp -f "${SRC_HELPER}" "${DIST_HELPER}"
/usr/sbin/chown root:wheel "${DIST_HELPER}"
/bin/chmod 755 "${DIST_HELPER}"
/usr/bin/xattr -d com.apple.quarantine "${DIST_HELPER}" 2>/dev/null

# Copy new Helper plist
/bin/cp -f "${SRC_HELPER_PLIST}" "${DIST_HELPER_PLIST}"
/usr/sbin/chown root:wheel "${DIST_HELPER_PLIST}"
/bin/chmod 644 "${DIST_HELPER_PLIST}"
/usr/bin/xattr -d com.apple.quarantine "${DIST_HELPER_PLIST}" 2>/dev/null

# Restart Helper using kickstart
/bin/launchctl kickstart -k system/Dev.ServBay.macOS.ServBay.Helper

# Function to check if Helper is running
check_helper_running() {
    /bin/launchctl list | grep -q "Dev.ServBay.macOS.ServBay.Helper"
    return $?
}

# Get new PID
new_pid=$(get_helper_pid)
echo "New PID: $new_pid"

# Check if PID has changed
if [[ "$current_pid" != "$new_pid" ]]; then
    echo "Helper successfully restarted with new PID."
else
    echo "Helper restart with kickstart failed, attempting unload and load method..."

    # Unload current Helper
    /bin/launchctl unload ${DIST_HELPER_PLIST}

    # Reload Helper
    /bin/launchctl load -wF ${DIST_HELPER_PLIST}

    # Retry logic
    attempt=1
    while true; do
        if check_helper_running; then
            echo "Helper successfully started."
            break
        fi

        if [[ $attempt -ge $MAX_RETRIES ]]; then
            echo "Helper failed to start after $attempt attempts, restoring backup..."

            # Restore backup and restart
            if [[ -f ${BACKUP_HELPER} ]]; then
                /bin/cp -f "${BACKUP_HELPER}" "${DIST_HELPER}"
                /bin/launchctl load -wF ${DIST_HELPER_PLIST}
            fi

            exit 1
        fi

        echo "Helper not running, retrying in ${RETRY_DELAY} seconds... (Attempt $attempt)"
        sleep $RETRY_DELAY
        /bin/launchctl unload ${DIST_HELPER_PLIST}
        /bin/launchctl load -wF ${DIST_HELPER_PLIST}
        ((attempt++))
    done
fi

# If everything is successful, remove backup
if check_helper_running; then
    echo "Removing backup file..."
    /bin/rm -f "${BACKUP_HELPER}"
else
    echo "Helper is not running, backup file retained."
fi
