#!/usr/bin/env bash
# ********* Starting configuration *********
while getopts ":m:p:s:t:xh"  option; do
case "${option}" in
m) HOME_DIR=${OPTARG};;
p) PROXY_URL=${OPTARG};;
s) SERVER_ID=${OPTARG};;
t) TELEMETRY_PORT=${OPTARG};;
x) SKIP_SERVICE="true";;
h)
    echo "DESCRIPTION: Install Anypoint Monitoring OpenTelemetry Collector"
    echo "Usage: $0 [options]"
    echo " "
    echo "options:"
    echo "-h,       show help"
    echo "-m,       set home directory - defaults to MULE_HOME"
    echo "-p,       set HTTP/HTTPS proxy server URL"
    echo "          Example: -p https://user:password@https-server:1080"
    echo "-t,       set internal telemetry port"
    echo " "
    exit 0
    ;;
esac
done
shift "$((OPTIND-1))"

if [[ -z "$HOME_DIR" || ! -d "$HOME_DIR" ]]; then
    if [[ -d "$MULE_HOME" ]]; then
        HOME_DIR=$MULE_HOME
    else
        cd $(dirname $0)
        cd ../..
        HOME_DIR=`pwd`
    fi
fi

echo "MULE_HOME is set to ${HOME_DIR}"

# Detect JAVA_HOME if not provided by user
if [[ -z "$JAVA_HOME" ]]; then
    # Try to find Java in common locations
    if command -v java >/dev/null 2>&1; then
        # Java is in PATH, find its installation directory
        JAVA_PATH=$(which java)
        if [[ -L "$JAVA_PATH" ]]; then
            # Resolve symlink
            JAVA_PATH=$(readlink -f "$JAVA_PATH")
        fi
        # Go up two directories from bin/java to get JAVA_HOME
        JAVA_HOME=$(dirname "$(dirname "$JAVA_PATH")")
        echo "Auto-detected JAVA_HOME: $JAVA_HOME"
    else
        echo "Warning: Could not auto-detect JAVA_HOME. Please set JAVA_HOME environment variable."
        echo "Example: export JAVA_HOME=/path/to/java/home"
        JAVA_HOME=""
        exit 1
    fi
else
    echo "Using user-provided JAVA_HOME: $JAVA_HOME"
fi

AM_HOME=${HOME_DIR}/am
source ${AM_HOME}/bin/tools/pid-file

installServiceAgent() {
    # Configuring otel collector as a service
    SERVICE_UNIT_FILE="/lib/systemd/system/am-otel-collector.service"
    DIRECTORY_WATCHER_SERVICE_UNIT_FILE="/lib/systemd/system/am-directory-watcher.service"
    
    [[ -f /bin/systemctl ]] && SYSTEMCTL_EXEC=/bin/systemctl || SYSTEMCTL_EXEC=/usr/bin/systemctl
    if [[ ! -d "$SERVICE_UNIT_FILE" ]]; then
        echo "Copying otel collector service configuration"
        sudo cp ${AM_HOME}/config/am-otel-collector.template.service $SERVICE_UNIT_FILE
        sudo sed -i '' -e "s/\$muleHome\\$/${HOME_DIR//\//\\/}/g" $SERVICE_UNIT_FILE > /dev/null 2>&1
        sudo sed -i '' -e "s/\$javaHome\\$/${JAVA_HOME//\//\\/}/g" $SERVICE_UNIT_FILE > /dev/null 2>&1
        GOMEMLIMIT=26MiB
        sudo sed -i '' -e "s/\$gomemlimit\\$/${GOMEMLIMIT//\//\\/}/g" $SERVICE_UNIT_FILE > /dev/null 2>&1
    fi

    # Process DirectoryWatcher service configuration
    if [[ ! -d "$DIRECTORY_WATCHER_SERVICE_UNIT_FILE" ]]; then
        echo "Copying directory watcher service configuration"
        sudo cp ${AM_HOME}/config/am-directory-watcher.template.service $DIRECTORY_WATCHER_SERVICE_UNIT_FILE
        sudo sed -i '' -e "s/\$muleHome\\$/${HOME_DIR//\//\\/}/g" $DIRECTORY_WATCHER_SERVICE_UNIT_FILE > /dev/null 2>&1
        
        # Replace javaHome placeholder if JAVA_HOME is available
        if [[ -n "$JAVA_HOME" ]]; then
            sudo sed -i '' -e "s/\$javaHome\\$/${JAVA_HOME//\//\\/}/g" $DIRECTORY_WATCHER_SERVICE_UNIT_FILE > /dev/null 2>&1
            echo "DirectoryWatcher service configured with JAVA_HOME: $JAVA_HOME"
        else
            echo "Warning: DirectoryWatcher service installed but JAVA_HOME not set"
        fi
    fi

    # Create pid file to run as a service in sudo directory
    createOtelCollectorPidFile true /etc/otel-collector
    createDirectoryWatcherPidFile true /etc/directory-watcher
    sudo systemctl daemon-reload
}

configureProxyUrl() {
    PROXY_URL_FILE=${AM_HOME}/config/proxy.url
    # Remove existing proxy url file
    if [[ -f ${PROXY_URL_FILE} ]]; then
        rm ${PROXY_URL_FILE}
    fi
    # Check and write the proxy URL file if PROXY_URL or HTTPS_PROXY is set
    local proxy_value="${PROXY_URL:-$HTTPS_PROXY}"
    if [[ -n "$proxy_value" ]]; then
        printf "%s\n" "$proxy_value" > "${PROXY_URL_FILE}"
        printf "Set the proxy to %s.\n" "$proxy_value"
    fi
}

configureTelemetryPort() {
    TELEMETRY_PORT_FILE=${AM_HOME}/config/telemetry.port
    # helper: returns 0 if free, 1 if in use or unknown
    is_port_free() {
        local _port="$1"
        if command -v lsof >/dev/null 2>&1; then
            lsof -nP -iTCP:"${_port}" -sTCP:LISTEN >/dev/null 2>&1 && return 1 || return 0
        elif command -v ss >/dev/null 2>&1; then
            ss -ltn 2>/dev/null | awk '{print $4}' | grep -E "[:\.]${_port}$" >/dev/null 2>&1 && return 1 || return 0
        elif command -v netstat >/dev/null 2>&1; then
            netstat -ltn 2>/dev/null | awk '{print $4}' | grep -E "[:\.]${_port}$" >/dev/null 2>&1 && return 1 || return 0
        else
            # If we cannot determine, assume free to avoid false positives
            return 0
        fi
    }
    # Remove existing telemetry port file
    if [[ -f ${TELEMETRY_PORT_FILE} ]]; then
        rm ${TELEMETRY_PORT_FILE}
    fi
    # Write telemetry port: use provided value, else default to 8888
    if [[ -n "$TELEMETRY_PORT" ]]; then
        # Trim whitespace
        local _tp
        _tp=$(echo -n "$TELEMETRY_PORT" | tr -d '[:space:]')
        # Validate numeric and range (1024-65535)
        if [[ $_tp =~ ^[0-9]+$ ]] && (( _tp >= 1024 && _tp <= 65535 )); then
            if is_port_free "$_tp"; then
                printf "%s\n" "$_tp" > "${TELEMETRY_PORT_FILE}"
                printf "Set the telemetry port to %s.\n" "$_tp"
            else
                printf "ERROR: Telemetry port %s is already in use. Please re-run install with -t <free port>.\n"
                exit 1
            fi
        else
            printf "ERROR: Invalid telemetry port '%s'. Must be an integer between 1024 and 65535.\n" "$TELEMETRY_PORT"
            exit 1
        fi
    else
        if is_port_free "8888"; then
            printf "%s\n" "8888" > "${TELEMETRY_PORT_FILE}"
            printf "Set the telemetry port to default %s.\n" "8888"
        else
            printf "ERROR: Default telemetry port 8888 is in use. Please re-run install with -t <free port>.\n"
            exit 1
        fi
    fi
}

configureAgent() {
    echo "Configuring agent..."
    if (type -p java) || ([[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]); then
        java -jar ${AM_HOME}/lib/agent-configurator.jar ${HOME_DIR}
    else
        echo "Error pushing configuration because Java is not installed"
    fi
}

rm -f ${AM_HOME}/config/pipelines/*.yml > /dev/null 2>&1
if [[ -z "$SERVER_ID" ]]; then
    rm ${AM_HOME}/config/server.id > /dev/null 2>&1
else
    touch ${AM_HOME}/config/server.id > /dev/null 2>&1
    echo "$SERVER_ID" > "${AM_HOME}/config/server.id"
fi

# Create pid file in home
createOtelCollectorPidFile false ${AM_HOME}
createDirectoryWatcherPidFile false ${AM_HOME}
configureProxyUrl
configureTelemetryPort
configureAgent

if [[ -z "$SKIP_SERVICE" ]]; then
    if [[ "$OSTYPE" != "darwin"* ]]; then
        read -p "Do you want to use monitoring as a service? [y|n] " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            # Warn if services are already installed
            if [[ -f "/lib/systemd/system/am-otel-collector.service" ]]; then
                echo "WARNING: Service 'am-otel-collector' is already installed. It will be reused/updated."
            fi
            if [[ -f "/lib/systemd/system/am-directory-watcher.service" ]]; then
                echo "WARNING: Service 'am-directory-watcher' is already installed. It will be reused/updated."
            fi
            echo "Installing Anypoint Monitoring OpenTelemetry Collector as a service..."
            installServiceAgent
        fi
        echo "Next Steps:"
        echo "1. Restart your Mule server completely to ensure all configurations are loaded properly"
        echo "2. After restarting Mule, run the setup script to start monitoring:"
        echo "   $AM_HOME/bin/setup"
    fi
else
  echo "Skipping service installation prompt. Anypoint Monitoring OpenTelemetry Collector will run as a standalone process."
fi

exit 0
