#!/bin/sh


OS_TYPE=$(uname)
ACCESS_KEY=$1
SERVER_IP=$2
INSTALL_ROOT=${3:-/usr}
TYPE=${4:-swinstall}
ACTION=${5:-install}
CONF="$INSTALL_ROOT/whatap/infra/conf/whatap.conf"
SERVICE_SCRIPT="$INSTALL_ROOT/whatap/whatap-infra"
SERVICE_SCRIPT_TMP="$INSTALL_ROOT/whatap/whatap-infra.tmp"


# Function: convert version string X.Y.Z to integer XXXYYZZ for comparison
ver_to_int() {
    IFS='.' read major minor patch <<EOF
$1
EOF
    printf "%d%02d%02d" "$major" "$minor" "$patch"
}


# SERVER-1901: agent shutdown / orphan reaping, implemented here rather than
# delegated to "$SERVICE_SCRIPT stop".
#
# The service script gained this same sweep, but at install time the script on
# disk is still the PREVIOUS version - which stops only the pid recorded in the
# pid file and leaves the forked "foreground" worker behind. Those workers are
# reparented to init and accumulate one per install/patch cycle, and a customer
# cannot reasonably be asked to hunt them down by hand. Carrying the logic in
# install.sh means the very first deployment of the fix already cleans up the
# orphans left by every previous cycle. It runs again from the new service
# script afterwards; the second pass is a no-op because nothing is left.
#
# Matching rules are the same as the service script: an exact whitespace
# delimited token equal to the absolute binary path. A bare "whatap_infrad"
# match would also hit agents installed under a different root on the same host
# and unrelated processes that merely mention the binary, and a substring match
# on the path would additionally hit the "whatap_infrad.bak-<timestamp>" copies
# the patch script leaves beside it.
AGENT_BIN="$INSTALL_ROOT/whatap/infra/whatap_infrad"

is_valid_pid() {
    case "$1" in
        ''|*[!0-9]*) return 1 ;;
        *) [ "$1" -gt 0 ] ;;
    esac
}

agent_pids() {
    ps -ef 2>/dev/null | awk -v bin="$AGENT_BIN" '
        { for (i = 1; i <= NF; i++) if ($i == bin) { print $2; break } }'
}

# The agent's SIGTERM handler kills its child and then sleeps 5s before exiting,
# so poll for up to 10s before escalating instead of guessing a fixed sleep.
wait_agent_exit() {
    waited=0
    while [ "$waited" -lt 10 ]; do
        if [ -z "$(agent_pids)" ]; then
            return 0
        fi
        sleep 1
        waited=$((waited + 1))
    done
    return 1
}

stop_agent_processes() {
    if [ -z "$(agent_pids)" ]; then
        return 0
    fi

    echo "Stopping whatap-infra processes before touching the installation..."
    for p in $(agent_pids); do
        is_valid_pid "$p" || continue
        echo "  SIGTERM -> PID $p"
        kill -TERM "$p" 2>/dev/null
    done

    if wait_agent_exit; then
        echo "  all whatap-infra processes stopped"
        return 0
    fi

    for p in $(agent_pids); do
        is_valid_pid "$p" || continue
        echo "  still alive, SIGKILL -> PID $p"
        kill -9 "$p" 2>/dev/null
    done
    sleep 2

    if [ -n "$(agent_pids)" ]; then
        echo "  WARNING: whatap-infra processes survived SIGKILL: $(agent_pids | tr '\n' ' ')"
    fi
}

# 운영체제에 따른 패키지 설치
if [ "$OS_TYPE" = "SunOS" ]; then
    echo "OS : SunOS"
    exit 1
elif [ "$OS_TYPE" = "HP-UX" ]; then
    echo "OS : HP-UX"
    echo "Install type: $TYPE"
    echo "Action: $ACTION"

    if [ "$ACTION" = "uninstall" ]; then
        echo "Uninstalling whatap-infra..."

        if [ "$TYPE" = "swinstall" ]; then
            echo "Using swremove for uninstall"

            # SERVER-1901: stop the agent (and reap orphaned workers) BEFORE SD
            # deletes the files. Without this the agent keeps running while its
            # binary and libraries disappear underneath it, which is how a box
            # ends up with live processes whose executable no longer exists.
            stop_agent_processes

            swremove whatap-infra
            SW_RC=$?
            if [ $SW_RC -ne 0 ] && [ $SW_RC -ne 2 ]; then
                echo "Error: swremove failed (rc=$SW_RC). See /var/adm/sw/swagent.log"
                exit 1
            fi

            # SERVER-1901: SD does not own these links - install.sh created them
            # with ln -sf - so swremove leaves them dangling. Remove them here,
            # the same way the cp path already does.
            rm -f /sbin/init.d/whatap-infra
            rm -f /sbin/rc3.d/S999whatap-infra
            rm -f /sbin/init.d/whatap-updater
        elif [ "$TYPE" = "cp" ]; then
            echo "Using manual removal for cp installation"

            # SERVER-1901: stop before unlinking anything, and use the built-in
            # sweep instead of "$SERVICE_SCRIPT stop" so orphaned workers left by
            # an older service script are reaped too.
            stop_agent_processes

            # Remove service links
            rm -f /sbin/init.d/whatap-infra
            rm -f /sbin/rc3.d/S999whatap-infra
            rm -f /sbin/init.d/whatap-updater

            # Remove whatap directory
            if [ -d "$INSTALL_ROOT/whatap" ]; then
                echo "Removing $INSTALL_ROOT/whatap directory..."
                rm -rf "$INSTALL_ROOT/whatap"
            fi

            echo "Manual removal completed"
        else
            echo "Error: Invalid installation type '$TYPE'. Use 'swinstall' or 'cp'"
            exit 1
        fi

        echo "Uninstall Complete."
        exit 0

    elif [ "$ACTION" = "install" ]; then
        echo "Installing whatap-infra..."

        if [ "$TYPE" = "swinstall" ]; then
        # swagentd 프로세스 확인
        PROCESS_COUNT=$(ps -ef | grep swagentd | grep -v grep | wc -l)

        # 프로세스 개수가 1 미만인지 확인
        if [ "$PROCESS_COUNT" -lt 1 ]; then
            echo "swagentd check fail"
            echo "please execute '/usr/sbin/swagentd -r'"
            exit 1
        else
            echo "swagentd check ok"

            DO_REMOVE=false
            INSTALLED_VER=$(swlist -l product whatap-infra 2>/dev/null | awk '/whatap-infra/ {print $2}')
            if [ -n "$INSTALLED_VER" ]; then
                echo "Detected installed version: $INSTALLED_VER"
                INST_INT=$(ver_to_int "$INSTALLED_VER")
                THRESHOLD=$(ver_to_int "1.4.4")
                if [ "$INST_INT" -le "$THRESHOLD" ]; then
                    echo "Version <= 1.4.4 detected; scheduling removal before install"
                    DO_REMOVE=true
                fi
            fi

            # SERVER-1901: stop the running agent and reap orphaned workers
            # before anything touches the installed files. Overwriting a binary
            # that a live process still holds is what leaves a fileset half
            # installed, and orphans from previous cycles are only cleaned here
            # (the service script on disk is still the pre-fix version).
            stop_agent_processes

            # Remove old package if needed
            if $DO_REMOVE; then
                echo "Removing existing whatap-infra..."
                swremove whatap-infra
                SW_RC=$?
                if [ $SW_RC -ne 0 ] && [ $SW_RC -ne 2 ]; then
                    echo "Error: swremove failed (rc=$SW_RC). See /var/adm/sw/swagent.log"
                    exit 1
                fi
            fi

            CURRENT_DIR=$(pwd)
            TARGET_DEPOT=$(find ./ -type d -name "whatap-infra*depot" | awk -F'-' '{print $NF, $0}' | sort -n -t. -k1,1 -k2,2 -k3,3 | awk '{$1=""; print substr($0,2)}' | tail -n 1)

            TARGET_PATH="$CURRENT_DIR/$TARGET_DEPOT"
            echo "$TARGET_PATH"

            swinstall -x mount_all_filesystems=false -s "$TARGET_PATH" whatap-infra:$INSTALL_ROOT
            SW_RC=$?
            # SERVER-1901: swinstall's exit status was never checked, so a
            # failed install still ran the post-install steps and printed
            # "Install Complete." - a real customer install lost a day to that.
            # SD returns 0 on success, 2 for warnings, 1 (or other) on error.
            if [ $SW_RC -eq 2 ]; then
                echo "WARNING: swinstall completed with warnings (rc=2). See /var/adm/sw/swagent.log"
            elif [ $SW_RC -ne 0 ]; then
                echo "Error: swinstall failed (rc=$SW_RC)."
                echo "  agent log : /var/adm/sw/swagent.log"
                echo "  verify    : swlist -l fileset -a state whatap-infra"
                exit 1
            fi
        fi

    elif [ "$TYPE" = "cp" ]; then
        echo "Using cp installation method"

        # Find the source directory containing whatap files
        CURRENT_DIR=$(pwd)
        SOURCE_DIR=$(find ./ -type d -name "whatap-infra*" | grep -v depot | head -1)

        if [ -z "$SOURCE_DIR" ]; then
            echo "Error: No whatap-infra source directory found"
            exit 1
        fi

        echo "Source directory: $SOURCE_DIR"

        # Create target directory
        mkdir -p "$INSTALL_ROOT/whatap"

        # Copy files
        echo "Copying files from $SOURCE_DIR to $INSTALL_ROOT/whatap/"
        cp -r "$SOURCE_DIR"/* "$INSTALL_ROOT/whatap/"

        if [ $? -ne 0 ]; then
            echo "Error: Failed to copy files"
            exit 1
        fi

        echo "Files copied successfully"

    else
        echo "Error: Invalid installation type '$TYPE'. Use 'swinstall' or 'cp'"
        exit 1
    fi

    # Common post-installation steps for both methods
    sed "s|/usr/whatap|$INSTALL_ROOT/whatap|g" $SERVICE_SCRIPT > $SERVICE_SCRIPT_TMP
    mv $SERVICE_SCRIPT_TMP $SERVICE_SCRIPT
    chmod 755 $SERVICE_SCRIPT
    ln -sf $SERVICE_SCRIPT /sbin/init.d/whatap-infra
    ln -sf /sbin/init.d/whatap-infra /sbin/rc3.d/S999whatap-infra

    # Setup whatap-updater service
    UPDATER_SCRIPT="$INSTALL_ROOT/whatap/whatap-updater"
    UPDATER_SCRIPT_TMP="$INSTALL_ROOT/whatap/whatap-updater.tmp"
    if [ -f "$UPDATER_SCRIPT" ]; then
        sed "s|/usr/whatap|$INSTALL_ROOT/whatap|g" "$UPDATER_SCRIPT" > "$UPDATER_SCRIPT_TMP"
        mv "$UPDATER_SCRIPT_TMP" "$UPDATER_SCRIPT"
        chmod 755 "$UPDATER_SCRIPT"
        ln -sf "$UPDATER_SCRIPT" /sbin/init.d/whatap-updater
    fi

    PYTHON_FILE=$INSTALL_ROOT/whatap/infra/whatap_infrad
    PYTHON_FILE_TMP=$INSTALL_ROOT/whatap/infra/whatap_infrad.tmp
    if [ -f $PYTHON_FILE ]; then
        sed "s|/usr/whatap/infra|$INSTALL_ROOT/whatap/infra|g" $PYTHON_FILE > $PYTHON_FILE_TMP
        mv $PYTHON_FILE_TMP $PYTHON_FILE
        chmod 755 $PYTHON_FILE
    fi

    PYTHON_FILE2=$INSTALL_ROOT/whatap/infra/lib/lib/python2.7/site-packages/whatap/agent/conf/configure.py
    PYTHON_FILE2_TMP=$INSTALL_ROOT/whatap/infra/lib/lib/python2.7/site-packages/whatap/agent/conf/configure.py.tmp
    if [ -f $PYTHON_FILE2 ]; then
        sed "s|/usr/whatap/infra|$INSTALL_ROOT/whatap/infra|g" $PYTHON_FILE2 > $PYTHON_FILE2_TMP
        mv $PYTHON_FILE2_TMP $PYTHON_FILE2
    fi

    if [ -f "$CONF" ]; then
        echo "File $CONF exists."
        echo "Do you want to overwrite the file? (y/n):"
        read USER_INPUT

        if [ "$USER_INPUT" = "y" ] || [ "$USER_INPUT" = "Y" ]; then
            CREATED_TIME=`perl -e 'use Time::HiRes qw(gettimeofday); ($seconds, $microseconds) = gettimeofday; print ($seconds * 1000 + int($microseconds / 1000)), "\n";'`
            rm $CONF
            echo "license=$ACCESS_KEY" | tee $CONF
            echo "whatap.server.host=$SERVER_IP" | tee -a $CONF
            echo "createdtime=$CREATED_TIME" | tee -a $CONF
        else
            echo "File not deleted."
        fi
    else
        CREATED_TIME=`perl -e 'use Time::HiRes qw(gettimeofday); ($seconds, $microseconds) = gettimeofday; print ($seconds * 1000 + int($microseconds / 1000)), "\n";'`
        echo "license=$ACCESS_KEY" | tee $CONF
        echo "whatap.server.host=$SERVER_IP" | tee -a $CONF
        echo "createdtime=$CREATED_TIME" | tee -a $CONF
    fi

    echo "Install Complete."

    else
        echo "Error: Invalid action '$ACTION'. Use 'install' or 'uninstall'"
        exit 1
    fi
else
    echo "Unsupported OS: $OS_TYPE"
    exit 1
fi
