#!/bin/sh

# Check valid URL path
# 1 - Return Result
# 2 - URL
checkValidUrl()
{
    RESULT_VALID_URL="$1"
    URL=`echo "$2" | tr [:upper:] [:lower:]`

    if [ `echo $URL | cut -c1-5` = "http:" -o `echo $URL | cut -c1-6` = "https:" ]; then
        eval $RESULT_VALID_URL="Y"
    else
        eval $RESULT_VALID_URL="N"
    fi
}

# Extract server address from name in format obm-nix-%PORT%-%HOST_NAME%-%PROTOCOL%-%OWNER_ID%.sh, where %PROTOCOL% is "http"/"https"
# 1 - Return HostAddr
# 2 - Return OwnerID
# 3 - Name
parseHostAddrFromName()
{
    RESULT_HOST_ADDR="$1"
    RESULT_OWNER_ID="$2"
    # add prefix here to avoid failure case "-abc", prefix will be abandoned below
    NAME=`basename "prefix$3"`

    eval $RESULT_HOST_ADDR=""
    eval $RESULT_OWNER_ID=""

    PROTOCOL=""
    SUFFIX_NAME=""
    # remove file ext
    NAME=`echo "$NAME" | sed "s|\.[^\.]*$||"`

    while true; do
        # sed "s|^[^-]*$||": replace whole string with empty if whole string is without '-'
        if [ -z "`echo $NAME | sed \"s|^[^-]*$||\"`" ]; then
            break;
        fi
        # get suffix
        SUFFIX=`echo "$NAME" | sed "s|^.*-||"`
        # remove suffix
        NAME=`echo "$NAME" | sed "s|-[^-]*$||"`
        if [ ! -z "`echo $SUFFIX | grep \"^https\"`" ]; then
            PROTOCOL="https"
            break;
        fi
        if [ ! -z "`echo $SUFFIX | grep \"^http\"`" ]; then
            PROTOCOL="http"
            break;
        fi
        if [ -z "$SUFFIX_NAME" ]; then
            SUFFIX_NAME="$SUFFIX"
        else
            SUFFIX_NAME="$SUFFIX-$SUFFIX_NAME"
        fi
    done

    if [ ! -z "$PROTOCOL" ]; then
        # remove prefix
        NAME=`echo "$NAME" | sed "s|[^-]*-||"`
        while true; do
            # sed "s|^[^-]*$||": replace whole string with empty if whole string is without '-'
            if [ -z "`echo $NAME | sed \"s|^[^-]*$||\"`" ]; then
                break;
            fi
            # PORT must be either a number or empty
            PORT=`echo "$NAME" | cut -d'-' -f1 | sed "s|.*[^0-9].*||"`
            NAME=`echo "$NAME" | sed "s|[^-]*-||"`
            # check if PORT is valid
            if [ ! -z "$PORT" ] && [ "$PORT" -le 65535 ] && [ "$PORT" -ge 0 ]; then
                if [ ! -z "$NAME" ]; then
                    eval "$RESULT_HOST_ADDR=\"$PROTOCOL://$NAME:$PORT\""
                fi
                break;
            fi
        done
    fi
    if [ ! -z "$SUFFIX_NAME" ]; then
        # remove character 'O' and string following it
        # this is not number "zero", it is a upper case 'o'
        SUFFIX_NAME=`echo "$SUFFIX_NAME" | sed "s|O[^O]*$||"`
        eval "$RESULT_OWNER_ID=\"$SUFFIX_NAME\""
    fi
}

# Search name in format obm-nix-%PORT%-%HOST_NAME%-%PROTOCOL%-%OWNER_ID%.rpm, where %PROTOCOL% is "http"/"https" from all running processes
# 1 - Return HostAddr
# 2 - Return OwnerID
# 3 - Filter File Ext
parseHostAddrFromSearch()
{
    RESULT_HOST_ADDR="$1"
    RESULT_OWNER_ID="$2"
    SEARCH_EXT="$3"

    eval $RESULT_HOST_ADDR=""
    eval $RESULT_OWNER_ID=""

    HOST_ADDR=""
    OWNER_ID=""

    ORIGINAL_IFS="$IFS"
    DIST=`grep -w ID /etc/os-release | awk -F '=' '{print $2}'`
    if [ "$DIST" = "ubuntu" -o "$DIST" = "debian" ]; then
        # space MUST NOT be added in between the quote, this is to define newline as separator
        IFS='
'
    else
        IFS=$'\n'
    fi

    if [ "$MY_PLATFORM" = "aix" ] ; then
        INSTALLER_LIST=$(ps -ef | grep "$SEARCH_EXT" | grep -v "grep")
    else
        INSTALLER_LIST=$(ps ax -o command | grep "$SEARCH_EXT" | grep -v "grep")
    fi
    # for word in `ps ax | grep $SEARCH_EXT | grep -v grep`; do
    echo "$INSTALLER_LIST" | while read word; do
        echo "Checking host address... $word"
        parseHostAddrFromName HOST_ADDR OWNER_ID "$word"
        if [ ! -z "$HOST_ADDR" ]; then
            eval "$RESULT_HOST_ADDR=\"$HOST_ADDR\""
            if [ ! -z "$OWNER_ID" ]; then
                eval "$RESULT_OWNER_ID=\"$OWNER_ID\""
            fi
            break;
        fi
    done

    TEMP_DIR="/tmp/obm"
    TEMP_FILE="$TEMP_DIR/installer_filename.txt"
    if [ -z "$HOST_ADDR" ] && [ -f "$TEMP_FILE" ]; then
        while read -r word; do
            echo "Checking host address from file... $word"
            parseHostAddrFromName HOST_ADDR OWNER_ID "$word"
            if [ ! -z "$HOST_ADDR" ]; then
                eval "$RESULT_HOST_ADDR=\"$HOST_ADDR\""
                if [ ! -z "$OWNER_ID" ]; then
                    eval "$RESULT_OWNER_ID=\"$OWNER_ID\""
                fi
                break
            fi
        done < "$TEMP_FILE"
        rm -rf "$TEMP_DIR"
    fi

    IFS="$ORIGINAL_IFS"
}

downloadViaOpenssl() {
    DOWNLOAD_URL="$1"
    SOURCE_FILE="$2"

    HOSTPORT=${DOWNLOAD_URL#https://}
    HOSTPORT=${HOSTPORT%%/*}
    # Add default port if missing
    if [[ "$HOSTPORT" != *:* ]]; then
        HOSTPORT="${HOSTPORT}:443"
    fi

    PATH_REQ=/${DOWNLOAD_URL#*://*/}
    PATH_REQ=/${PATH_REQ#*/}

    # Use openssl to send GET request and parse response properly
    {
        print "GET $PATH_REQ HTTP/1.1"
        print "Host: ${HOSTPORT}"
        print "User-Agent: AIX-openssl-client"
        print "Accept: */*"
        print "Connection: close"
        print ""
        sleep 1
    } | openssl s_client -quiet -connect "$HOSTPORT" 2>/dev/null | \
        perl -e '
            use strict;
            use warnings;
            binmode STDIN;
            binmode STDOUT;

            my $chunked = 0;
            my $length = undef;

            # Read and process headers
            while (1) {
                my $line = "";
                while (read(STDIN, my $char, 1)) {
                    $line .= $char;
                    last if $line =~ /\n$/;
                }
                $line =~ s/\r?\n$//;
                last if $line eq "";

                if ($line =~ /^Transfer-Encoding:\s*chunked/i) {
                    $chunked = 1;
                }
                if ($line =~ /^Content-Length:\s*(\d+)/i) {
                    $length = $1;
                }
            }

            if ($chunked) {
                # Read chunked encoding
                while (1) {
                    my $size_line = "";
                    while (read(STDIN, my $char, 1)) {
                        $size_line .= $char;
                        last if $size_line =~ /\n$/;
                    }
                    $size_line =~ s/\r?\n$//;
                    $size_line =~ s/;.*$//;
                    $size_line =~ s/^\s+|\s+$//g;
                    next if $size_line eq "";

                    unless ($size_line =~ /^[0-9a-fA-F]+$/) {
                        warn "Invalid chunk size: '$size_line'\n";
                        last;
                    }

                    my $size = hex($size_line);
                    last if $size == 0;

                    my $remaining = $size;
                    while ($remaining > 0) {
                        my $read = read(STDIN, my $buf, ($remaining > 8192) ? 8192 : $remaining);
                        last unless $read;
                        print $buf;
                        $remaining -= $read;
                    }

                    # Discard CRLF
                    read(STDIN, my $crlf, 2);
                }
            } elsif (defined $length) {
                # Read based on Content-Length
                my $remaining = $length;
                while ($remaining > 0) {
                    my $read = read(STDIN, my $buf, ($remaining > 8192) ? 8192 : $remaining);
                    last unless $read;
                    print $buf;
                    $remaining -= $read;
                }
            } else {
                # Unknown length: stream until EOF
                while (read(STDIN, my $buf, 8192)) {
                    print $buf;
                }
            }
        ' > "$SOURCE_FILE"
}

# Download and setup prepackaged components
# 1 - Return Result
# 2 - URL
# 3 - File Name
# 4 - URL Argu
# 5 - Destination
# 6 - Package Type
downloadAndSetupComponent()
{
    SETUP_RESULT="$1"
    SOURCE_URL_HOME="$2"
    SOURCE_FILE="$3"
    SOURCE_URL_ARGU="$4"
    DESTINATION_DIR="$5"
    PKG_TYPE="$6"

    if [ ! -z "$SOURCE_URL_ARGU" ]; then
        DOWNLOAD_URL_UNENCODED="$SOURCE_URL_HOME/$SOURCE_FILE?$SOURCE_URL_ARGU"
    else
        DOWNLOAD_URL_UNENCODED="$SOURCE_URL_HOME/$SOURCE_FILE"
    fi
    DOWNLOAD_URL=$(echo "$DOWNLOAD_URL_UNENCODED" | sed -e 's/ /%20/g' -e 's/(/%28/g' -e 's/)/%29/g')

    CURRENT_DIR=`pwd`
    if [ "$PKG_TYPE" = "jvm" ] ; then
        TARGET_DIR="$DESTINATION_DIR/jvm"
    else
        TARGET_DIR="$DESTINATION_DIR"
    fi

    echo "Downloading file... $SOURCE_FILE"
    if [ "$MY_PLATFORM" = "solaris" ]; then
        /usr/sfw/bin/wget --no-check-certificate "$DOWNLOAD_URL" -O "$SOURCE_FILE"
    elif [ "$MY_PLATFORM" = "aix" ]; then
        downloadViaOpenssl "$DOWNLOAD_URL" "$SOURCE_FILE"
    else
        curl -k "$DOWNLOAD_URL" -o "$SOURCE_FILE"
    fi
    if [ -f "$SOURCE_FILE" ]; then
        echo "Download file completed"
        if [ ! -d "$TARGET_DIR" ]; then
            mkdir "$TARGET_DIR"
        fi
        echo "Untar component file to $TARGET_DIR"
        if [ "$MY_PLATFORM" = "solaris" ] ; then
            cd "$TARGET_DIR"
            gzip -cdf "$CURRENT_DIR/$SOURCE_FILE" | /usr/sfw/bin/gtar xf - > /dev/null
            cd "$CURRENT_DIR"
        elif [ "$MY_PLATFORM" = "aix" ] ; then
            gunzip -c "$SOURCE_FILE" | tar -xvf - -C "$TARGET_DIR" > /dev/null
        elif [ "$MY_PLATFORM" = "others" ] ; then
            tar -xzf "$SOURCE_FILE" -C "$TARGET_DIR" > /dev/null
        fi
        rm "$SOURCE_FILE"
        eval $SETUP_RESULT="Y"
    else
        echo "Fail to download file from URL $DOWNLOAD_URL"
        eval $SETUP_RESULT="N"
    fi
}

# Verify and setup prepackaged components
# 1 - Return Result
# 2 - Source
# 3 - File Name
# 4 - Destination
# 5 - Package Type
verifyAndSetupComponent()
{
    SETUP_RESULT="$1"
    SOURCE_DIR="$2"
    SOURCE_FILE="$3"
    DESTINATION_DIR="$4"
    PKG_TYPE="$5"

    CURRENT_DIR=`pwd`
    if [ "$PKG_TYPE" = "jvm" ] ; then
        TARGET_DIR="$DESTINATION_DIR/jvm"
    else
        TARGET_DIR="$DESTINATION_DIR"
    fi

    if [ -f "$SOURCE_DIR/$SOURCE_FILE" ]; then
        if [ ! -d "$TARGET_DIR" ]; then
            mkdir "$TARGET_DIR"
        fi
        echo "Untar $SOURCE_FILE to $TARGET_DIR"
        if [ "$MY_PLATFORM" = "solaris" ] ; then
            cd "$TARGET_DIR"
            gzip -cdf "$SOURCE_DIR/$SOURCE_FILE" | /usr/sfw/bin/gtar xf - > /dev/null
            cd "$CURRENT_DIR"
        elif [ "$MY_PLATFORM" = "aix" ] ; then
            gunzip -c "$SOURCE_DIR/$SOURCE_FILE" | tar -xvf - -C "$TARGET_DIR" > /dev/null
        elif [ "$MY_PLATFORM" = "others" ] ; then
            tar -xzf "$SOURCE_DIR/$SOURCE_FILE" -C "$TARGET_DIR" > /dev/null
        fi
        eval $SETUP_RESULT="Y"
    else
        echo "$SOURCE_FILE not exists"
        eval $SETUP_RESULT="N"
    fi
}

# Prepare prepackaged components
# 1 - Return Result
preparePackagedComponents()
{
    PREPARE_RESULT="$1"
    eval $PREPARE_RESULT="N"

    RESULT_JVM_HOME="$2"
    eval $RESULT_JVM_HOME="Y"

    URL_ARGU=""
    HOST_ADDR=""
    OWNER_ID=""

    DOWNLOAD_PGK="Y"
    # Parse host address
    if [ "$MODE" = "rpm" ]; then
        VAR_SEARCH_EXT="\\.rpm"
        parseHostAddrFromSearch HOST_ADDR OWNER_ID "$VAR_SEARCH_EXT"
    elif [ "$MODE" = "deb" ]; then
        VAR_SEARCH_EXT="\\.deb"
        parseHostAddrFromSearch HOST_ADDR OWNER_ID "$VAR_SEARCH_EXT"
    else
        parseHostAddrFromName HOST_ADDR OWNER_ID "$INSTALLER"
        if [ -z "$HOST_ADDR" ] && [ -d "$CLIENT_VERSION_PKG_DIR" ]; then
            echo "Using package in $CLIENT_VERSION_PKG_DIR"
            DOWNLOAD_PGK="N"
        fi
    fi

    if [ "$DOWNLOAD_PGK" = "N" ] ; then
        if [ ! -f "$PKG_DIR/version.txt" ]; then
            echo "Package version file not exists"
            return
        fi
        PKG_VERSION=`cat "$PKG_DIR/version.txt"`
        echo "Package version: $PKG_VERSION"
        MIN_VERSION="$(printf "$VERSION\n$PKG_VERSION\n" | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n | head -n1)"
        if [ "$MIN_VERSION" = "$VERSION" ] && [ "$PKG_VERSION" != "$VERSION" ]; then
            echo "Package version does not match with installer version: $VERSION"
            return
        fi
    else
        if [ -z "$HOST_ADDR" ]; then
            echo "Host address is not defined"
            return
        fi
        if [ -z "$OWNER_ID" ]; then
            echo "Owner ID is not defined"
            return
        fi
        IS_VALID_URL="N"
        checkValidUrl IS_VALID_URL "$HOST_ADDR"
        if [ "$IS_VALID_URL" = "N" ]; then
            echo "Invalid host address - $HOST_ADDR"
            return
        fi
        echo "Host address: $HOST_ADDR"

        # Check jvm url
        if [ ! -z "$JVM_URL" ] ; then
            IS_VALID_URL="N"
            checkValidUrl IS_VALID_URL "$JVM_URL"
            if [ "$IS_VALID_URL" = "N" ]; then
                JVM_URL="$HOST_ADDR/$JVM_URL"
            fi
        fi
        if [ -z "$JVM_URL" ] ; then
            echo "JVM package's URL is not defined"
            return
        fi

        # Check component url
        if [ ! -z "$COMPONENT_URL" ] ; then
            IS_VALID_URL="N"
            checkValidUrl IS_VALID_URL "$COMPONENT_URL"
            if [ "$IS_VALID_URL" = "N" ]; then
                COMPONENT_URL="$HOST_ADDR/$COMPONENT_URL"
            fi
        fi
        if [ -z "$COMPONENT_URL" ] ; then
            echo "Component package's URL is not defined"
            return
        fi

        URL_VERSION_ARGU_TAG="version"
        URL_OWNER_ID_ARGU_TAG="ownerid"
        if [ "$URL_VERSION_ARGU_TAG" != "" ] && [ "$URL_OWNER_ID_ARGU_TAG" != "" ]; then
          URL_ARGU="$URL_VERSION_ARGU_TAG=$VERSION&$URL_OWNER_ID_ARGU_TAG=$OWNER_ID"
        elif [ "$URL_OWNER_ID_ARGU_TAG" != "" ]; then
          URL_ARGU="$URL_OWNER_ID_ARGU_TAG=$OWNER_ID"
        elif [ "$URL_VERSION_ARGU_TAG" != "" ]; then
          URL_ARGU="$URL_VERSION_ARGU_TAG=$VERSION"
        fi
    fi

    # Prepare jvm
    PKG_JVM_FILE=""
    case "$SYSTEM_OS" in
        Linux*)
            if [ "$MY_ARCH" = "64" ]; then
                PKG_JVM_FILE="jre-std-linux-amd64.tar.gz"
            elif [ "$MY_ARCH" = "32" ]; then
                PKG_JVM_FILE="jre-std-linux-x86-586.tar.gz"
            elif [ "$MY_ARCH" = "arm64" ]; then
                PKG_JVM_FILE="jre-std-linux-arm64.tar.gz"
            elif [ "$MY_ARCH" = "arm32" ]; then
                PKG_JVM_FILE="jre-std-linux-arm32.tar.gz"
            fi
            ;;
        AIX)
            PKG_JVM_FILE="jre-std-aix-ppc64.tar.gz"
            ;;
        *)
            ;;
    esac
    if [ -z "$PKG_JVM_FILE" ]; then
        echo "No JVM package is defined"
        eval $RESULT_JVM_HOME="N"
    else
        for word in $PKG_JVM_FILE
        do
            if [ "$DOWNLOAD_PGK" = "N" ] ; then
                verifyAndSetupComponent SETUP_RESULT "$CLIENT_VERSION_PKG_DIR" "$word" "$APP_TMP" "jvm"
            else
                downloadAndSetupComponent SETUP_RESULT "$JVM_URL" "$word" "$URL_ARGU" "$APP_TMP" "jvm"
            fi
            if [ "$SETUP_RESULT" = "N" ] ; then
                echo "Failed to prepare JVM files."
                return
            fi
        done
    fi

    # Prepare other components
    PKG_COMPONENT_FILE=""
    # 50623: Use *-native-nix-x64.tar.gz because arm64 libraries were already moved here from *-native-nix-others.tar.gz (Task #42960)
    # if [ "$MY_ARCH" = "64" ] || [ "$MY_ARCH" = "powerpc64" ]; then
    if [ "$MY_ARCH" = "64" ] || [ "$MY_ARCH" = "powerpc64" ] || { [ "$MY_ARCH" = "arm64" ] && [ "$CLIENT_MAJOR_VERSION" != "$FALLBACK_MAJOR_VERSION" ]; }; then
        PKG_COMPONENT_FILE="app-common.tar.gz app-native-nix-x64.tar.gz app-nix-obm.tar.gz aua-common.tar.gz aua-native-nix-x64.tar.gz aua-nix-obm.tar.gz util-common.tar.gz util-nix-obm.tar.gz properties-common.tar.gz app-inst-nix-obm.tar.gz aua-inst-nix-obm.tar.gz app-custom-common-obm.tar.gz"
    elif [ "$MY_ARCH" = "32" ]; then
        PKG_COMPONENT_FILE="app-common.tar.gz app-native-nix-x86.tar.gz app-nix-obm.tar.gz aua-common.tar.gz aua-native-nix-x86.tar.gz aua-nix-obm.tar.gz util-common.tar.gz util-nix-obm.tar.gz properties-common.tar.gz app-inst-nix-obm.tar.gz aua-inst-nix-obm.tar.gz app-custom-common-obm.tar.gz"
    else
        PKG_COMPONENT_FILE="app-common.tar.gz app-native-nix-others.tar.gz app-nix-obm.tar.gz aua-common.tar.gz aua-native-nix-others.tar.gz aua-nix-obm.tar.gz util-common.tar.gz util-nix-obm.tar.gz properties-common.tar.gz app-inst-nix-obm.tar.gz aua-inst-nix-obm.tar.gz app-custom-common-obm.tar.gz"
    fi
    if [ -z "$PKG_COMPONENT_FILE" ]; then
        echo "No component package is defined"
    else
        for word in $PKG_COMPONENT_FILE
        do
            if [ "$DOWNLOAD_PGK" = "N" ] ; then
                verifyAndSetupComponent SETUP_RESULT "$CLIENT_VERSION_PKG_DIR" "$word" "$APP_TMP" "others"
            else
                downloadAndSetupComponent SETUP_RESULT "$COMPONENT_URL" "$word" "$URL_ARGU" "$APP_TMP" "others"
            fi
            if [ "$SETUP_RESULT" = "N" ] ; then
                echo "Failed to prepare component files."
                return
            fi
        done
    fi

    # Changed to not remove offline installer package
    # if [ "$DOWNLOAD_PGK" = "N" ] ; then
    #     rm -rf "$PKG_DIR"
    # fi
    eval $PREPARE_RESULT="Y"
}

# Function to get string segment with seperator '='
# e.g. $1 = "APP_HOME=/usr/local/obm APP_HOME=/root/Documents/obm" , $2 = 3
# then this function returns /root/Documents/obm
getColumnValue()
{
    STRING_PATTERN="$1"
    COL_NUM=$2
    echo $STRING_PATTERN | awk -F"=" '{print $'"${COL_NUM}"'}'
}

# Backup user setting files
# 1 - Backup Folder
backupUserConfig()
{
    TEMP_DIR="$1"
    BACKUP_DIR="$APP_HOME/$TEMP_DIR"

    # Get INIT_PATH to get APP_HOME from running service
    case "${SYSTEM_OS}" in
        Linux*)      INSTALL_TYPE=NIX ;;
        Solaris*)    INSTALL_TYPE=NIX ;;
        SunOS*)      INSTALL_TYPE=NIX ;;
        OpenBSD*)    INSTALL_TYPE=OPENBSD ;;
        *BSD*)       INSTALL_TYPE=BSD ;;
        AIX)         INSTALL_TYPE=NIX ;;
        **)          INSTALL_TYPE=NOT_SUPPORTED ;;
    esac

    # Initialize INIT_PATH to empty
    INIT_PATH=""
    # Set INIT_PATH for different OS
    if [ $INSTALL_TYPE = "NIX" ]; then
        if [ -z "$INIT_PATH" ]; then
            if [ -d /etc/init.d ]; then
                INIT_PATH=/etc/init.d
            elif [ -d /etc/rc.d/init.d ]; then
                INIT_PATH=/etc/rc.d/init.d
            fi
        fi

    elif [ $INSTALL_TYPE = "BSD" ]; then
        INIT_PATH=/usr/local/etc/rc.d

    elif [ $INSTALL_TYPE = "OPENBSD" ]; then
        # get OpenBSD version
        OPENBSD_VERSION=`uname -r | cut -f1 -d"."`

        if [ $OPENBSD_VERSION -ge 5 ]
        then
            INIT_PATH=/etc/rc.d
        else
            INIT_PATH=/etc
        fi
    fi

    # Get old APP_HOME
    if [ ! -z "$INIT_PATH" ]; then
        OBM_SCRIPT_FILE="$INIT_PATH/obmscheduler"
        if [ -f $OBM_SCRIPT_FILE ] ; then
            OBM_HOME_INFO=`cat $OBM_SCRIPT_FILE | grep APP_HOME=`
            APP_HOME_OLD=`getColumnValue "$OBM_HOME_INFO" 3`
        fi
    fi

    if [ -z "$APP_HOME_OLD" ]; then
        APP_HOME_OLD=$APP_HOME
    fi

    echo "  Backup user setting files"

    # directory for temporary keeping backup files
    if [ -d "$BACKUP_DIR" ]; then
        echo "  Remove previous cache"
        rm -rf "$BACKUP_DIR"
    fi
    mkdir "$BACKUP_DIR"

    # directory to be backup / restore
    DIR_NAME="log"
    for DIR in $DIR_NAME; do
        if [ -d "$APP_HOME_OLD/$DIR" ]; then
            echo "    Backup $DIR"
            mv -f "$APP_HOME_OLD/$DIR" "$BACKUP_DIR/$DIR"
        fi
    done

    # file to be backup / restore
    FILE_NAME="home.txt config.ini afc.opt cb.opt"
    for FILE in $FILE_NAME; do
        if [ -f "$APP_HOME_OLD/$FILE" ]; then
            echo "    Backup $FILE"
            mv -f "$APP_HOME_OLD/$FILE" "$BACKUP_DIR/$FILE"
        fi
    done

    # 28798: mbs directory / file to be backup / restore
    MBS_HOME="$APP_HOME_OLD/mbs"
    BACKUP_MBS_HOME="$BACKUP_DIR/mbs"
    if [ -d "$MBS_HOME" ]; then
        if [ -e "$BACKUP_MBS_HOME" ]; then
            rm -rf "$BACKUP_MBS_HOME"
        fi
        mkdir "$BACKUP_MBS_HOME"
        mkdir "$BACKUP_MBS_HOME/conf"
        if [ -f "$MBS_HOME/config.ini" ]; then
            echo "    Backup mbs/config.ini"
            mv -f "$MBS_HOME/config.ini" "$BACKUP_MBS_HOME"
        fi
        if [ -f "$MBS_HOME/conf/server.xml" ]; then
            echo "    Backup mbs/conf/server.xml"
            mv -f "$MBS_HOME/conf/server.xml" "$BACKUP_MBS_HOME/conf"
        fi
        if [ -d "$MBS_HOME/logs" ]; then
            echo "    Backup mbs/logs"
            mv -f "$MBS_HOME/logs" "$BACKUP_MBS_HOME"
        fi
    fi
    echo "  Backup finished"

    # Run uninstall to stop Scheduler, AUA services
    if [ -f "$APP_HOME_OLD/bin/uninstall.sh" ] ; then
        echo "  Uninstall previous version..."
        "$APP_HOME_OLD/bin/uninstall.sh" "no_privilege_check"

        echo "  Remove previous application files"
        APP_DATA="`ls "$APP_HOME_OLD" | sort `"
        for DATA in $APP_DATA; do
            if [ "$DATA" != "$TEMP_DIR" ] ; then
                if [ -d "$APP_HOME_OLD/$DATA" ] || [ -L "$APP_HOME_OLD/$DATA" ]; then
                    echo "    Remove directory $DATA"
                    rm -rf "$APP_HOME_OLD/$DATA"
                else
                    if [ -z "`echo \"$APP_HOME_OLD/$DATA\" | grep ${INSTALLER}$`" ]; then
                        if [ -f "$APP_HOME_OLD/$DATA" ]; then
                            echo "    Remove file $DATA"
                            rm "$APP_HOME_OLD/$DATA"
                        fi
                    fi
                fi
            fi
        done
        echo "  Remove application files finished"
    else
        echo "No previous version found"
    fi
}

# Restore user data files
# 1 - Backup Directory
restoreUserConfig()
{
    # directory for temporary keeping backup files
    TEMP_DIR="$1"
    BACKUP_DIR="$APP_HOME/$TEMP_DIR"

    if [ -d "$BACKUP_DIR" ]; then
        echo "  Restore Previous Setting backup..."

        # directory to be backup / restore
        DIR_NAME="log"
        for DIR in $DIR_NAME; do
            if [ -d "$BACKUP_DIR/$DIR" ]; then
                echo "    Restore $DIR"
                mv -f "$BACKUP_DIR/$DIR" "$APP_HOME/$DIR"
            fi
        done

        # migration logic for properties file 'afc.opt' and 'cb.opt'.
        FILEPATH_UTIL="$APP_HOME/util/lib/installer-util.jar"
        CLASSNAME_UTIL=PropertiesMigration

        # file to be backup / restore
        FILE_NAME="home.txt config.ini afc.opt cb.opt"
        for FILE in $FILE_NAME; do
            if [ -f "$BACKUP_DIR/$FILE" ]; then
                JVM_EXEC="$JVM_HOME/bin/java"
                # afc.opt AND cb.opt need perform migration
                if [ "$FILE" = "afc.opt" ]; then
                    echo "    Restore application opt file (afc.opt)"
                    FILEPATH_OUTPUT="$BACKUP_DIR/afc.opt.new"
                    FILEPATH_DEFAULT="$BACKUP_DIR/afc.opt"
                    FILEPATH_CUSTOM="$APP_HOME/afc.opt"
                    "${JVM_EXEC}" -cp "${FILEPATH_UTIL}" "${CLASSNAME_UTIL}" "${FILEPATH_OUTPUT}" "${FILEPATH_DEFAULT}" "${FILEPATH_CUSTOM}"
                    mv -f "${FILEPATH_OUTPUT}" "${FILEPATH_CUSTOM}"
                else
                    if [ "$FILE" = "cb.opt" ]; then
                        echo "    Restore application opt file (cb.opt)"
                        FILEPATH_OUTPUT="$BACKUP_DIR/cb.opt.new"
                        FILEPATH_DEFAULT="$BACKUP_DIR/cb.opt"
                        FILEPATH_CUSTOM="$APP_HOME/cb.opt"
                        "${JVM_EXEC}" -cp "${FILEPATH_UTIL}" "${CLASSNAME_UTIL}" "${FILEPATH_OUTPUT}" "${FILEPATH_DEFAULT}" "${FILEPATH_CUSTOM}"
                        mv -f "${FILEPATH_OUTPUT}" "${FILEPATH_CUSTOM}"
                    else
                        echo "    Restore $FILE"
                        mv -f "$BACKUP_DIR/$FILE" "$APP_HOME/$FILE"
                    fi
                fi
            fi
        done

        # 28798: mbs directory / file to be backup / restore
        MBS_HOME="$APP_HOME/mbs"
        BACKUP_MBS_HOME="$BACKUP_DIR/mbs"
        if [ -d "$BACKUP_MBS_HOME" ]; then
            if [ ! -d "$MBS_HOME" ]; then
                mkdir "$MBS_HOME"
            fi
            if [ ! -d "$MBS_HOME/conf" ]; then
                mkdir "$MBS_HOME/conf"
            fi
            if [ -f "$BACKUP_MBS_HOME/config.ini" ]; then
                echo "    Restore mbs/config.ini"
                mv -f "$BACKUP_MBS_HOME/config.ini" "$MBS_HOME"
            fi
            if [ -f "$BACKUP_MBS_HOME/conf/server.xml" ]; then
                echo "    Restore mbs/conf/server.xml"
                mv -f "$BACKUP_MBS_HOME/conf/server.xml" "$MBS_HOME/conf"
            fi
            if [ -d "$BACKUP_MBS_HOME/logs" ]; then
                echo "    Restore mbs/logs"
                mv -f "$BACKUP_MBS_HOME/logs" "$MBS_HOME"
            fi
        fi

        rm -rf "$BACKUP_DIR"
        echo "  Previous Setting backup restored"
    fi
}

# ---------------------------------
# Initialize
cd `dirname "$0"`

INSTALLER="$0"
MODE="manual"
if [ ! -z "$1" ]; then
    if [ "$1" = "rpm" ]; then
        MODE="rpm"
    elif [ "$1" = "deb" ]; then
        MODE="deb"
    fi
fi
EXEC_HOME=`pwd`
APP_HOME=$EXEC_HOME
if [ ! -z "$2" ]; then
    APP_HOME="$2"
fi
PRIVILEGE_CHK=""
if [ ! -z "$3" ]; then
    PRIVILEGE_CHK="$3"
fi

APP_BIN=$APP_HOME/bin
TIMESTAMP_DIR=`date '+%y%m%d%H%M%S'`
APP_TMP="/tmp/_obm.$TIMESTAMP_DIR"
PKG_DIR="$EXEC_HOME/app.pkg"
TEMP_CONFIG_DIR="_oldcfg"

# get arch of this system
SYSTEM_OS=`uname`
MY_PLATFORM=""
case "$SYSTEM_OS" in
    AIX)
        MY_PLATFORM="aix"
        CPU=`uname -p`
        KERNEL_ARCH=`prtconf -k | sed -e 's/^.*\([0-9][0-9]\).*$/\1/'`
        MY_ARCH=${CPU}${KERNEL_ARCH}
        ;;
    Solaris* | SunOS*)
        MY_PLATFORM="solaris"
        case "`isainfo -b`" in
            32)
                MY_ARCH="32"
                ;;
            64)
                MY_ARCH="64"
                ;;
            *)
                MY_ARCH="Others"
                ;;
        esac
        ;;
    *)
        MY_PLATFORM="others"
        case "`uname -m`" in
            i[3-6]86)
                MY_ARCH="32"
                ;;
            x86_64 | amd64)
                MY_ARCH="64"
                ;;
            aarch64 | arm64)
                MY_ARCH="arm64"
                ;;
            armv7l)
                MY_ARCH="arm32"
                ;;
            *)
                MY_ARCH="Others"
                ;;
        esac
        ;;
esac

# Print Logging Message Header
echo "Log Time: `date`"

# Determine the OS information
OS_VERSION=$(uname -r)
echo "OS Info: $SYSTEM_OS $OS_VERSION $MY_ARCH"

PRODUCT_NAME="MindtimeProBackup"

# Define URLs of client versions
OLD_JVM_URL="obs/download/9/jvm"
OLD_COMPONENT_URL="obs/download/9/component"
FALLBACK_MAJOR_VERSION="9"

NEW_JVM_URL="obs/download/10/jvm"
NEW_COMPONENT_URL="obs/download/10/component"
VERSION="10.1.6.0"
NEW_CLIENT_MAJOR_VERSION=$(echo "$VERSION" | cut -d'.' -f1)

# Decide which client version to use
CLIENT_MAJOR_VERSION="$FALLBACK_MAJOR_VERSION"
# The JVM supported version before v10
JAVA_VERSION="1.8"
if [ "$SYSTEM_OS" = "Linux" ]; then
    MINIMUM_SUPPORTED_KERNEL_VERSION="4.0"
        # 50902: Some special/custom builds do not use - as delimeter
        # KERNEL_VERSION=$(echo "$OS_VERSION" | cut -d- -f1)  # Get only version part, strip any suffix
        KERNEL_VERSION=$(echo "$OS_VERSION" | sed 's/[^0-9.].*//')  # Get only version part (numbers and dots), strip any suffix
    if { [ "$MY_ARCH" = "64" ] || [ "$MY_ARCH" = "arm64" ]; } && \
            [ "$(printf '%s\n' "$MINIMUM_SUPPORTED_KERNEL_VERSION" "$KERNEL_VERSION" | sort -V | head -n1)" = "$MINIMUM_SUPPORTED_KERNEL_VERSION" ]; then
        CLIENT_MAJOR_VERSION="$NEW_CLIENT_MAJOR_VERSION"
        # The JVM supported version starting v10
        JAVA_VERSION="21.0"
    fi
elif [ "$SYSTEM_OS" = "FreeBSD" ]; then
    MINIMUM_SUPPORTED_BSD_VERSION="13.0"
        # 50902: Some special/custom builds do not use - as delimeter
        # BSD_VERSION=$(freebsd-version | cut -d- -f1)   # Sample result: 14.3-RELEASE, become 14.3 after cut
        BSD_VERSION=$(freebsd-version | sed 's/[^0-9.].*//')  # Get only version part (numbers and dots), strip any suffix
    # compare by sorting version with min version in ascending order and check if the first one is min version or not, similar to version >= min version
    if [ "$(printf '%s\n' "$MINIMUM_SUPPORTED_BSD_VERSION" "$BSD_VERSION" | sort -V | head -n1)" = "$MINIMUM_SUPPORTED_BSD_VERSION" ]; then
        CLIENT_MAJOR_VERSION="$NEW_CLIENT_MAJOR_VERSION"
        JAVA_VERSION="21.0"
    fi
elif [ "$SYSTEM_OS" = "AIX" ]; then
    CLIENT_MAJOR_VERSION="$NEW_CLIENT_MAJOR_VERSION"
    JAVA_VERSION="21.0"
fi

CLIENT_VERSION_PKG_DIR="$PKG_DIR/$CLIENT_MAJOR_VERSION"
if [ "$CLIENT_MAJOR_VERSION" = "$FALLBACK_MAJOR_VERSION" ]; then
    JVM_URL="$OLD_JVM_URL"
    COMPONENT_URL="$OLD_COMPONENT_URL"
    echo "$PRODUCT_NAME v$NEW_CLIENT_MAJOR_VERSION does not support this operating system version of your machine. Installing $PRODUCT_NAME v$CLIENT_MAJOR_VERSION instead."
else
    JVM_URL="$NEW_JVM_URL"
    COMPONENT_URL="$NEW_COMPONENT_URL"
fi

# ---------------------------- Check XL C++ Version ----------------------------
if [ "$SYSTEM_OS" = "AIX" ]; then
    REQUIRED_XLCPP_VERSION="16.1.0.10"
    INSTALLED_XLCPP_VERSION=$(lslpp -l | grep xlC.rte | awk '{print $2}')

    ver_to_number() {
        echo "$1" | awk -F. '{printf("%03d%03d%03d%03d\n", $1,$2,$3,$4)}'
    }

    if [ "$(ver_to_number "$INSTALLED_XLCPP_VERSION")" -lt "$(ver_to_number "$REQUIRED_XLCPP_VERSION")" ]; then
        echo "xlC.rte version $INSTALLED_XLCPP_VERSION is less than the required version $REQUIRED_XLCPP_VERSION."
        echo "Exit \"`basename $0`\" now!" && exit 1
    fi
    echo "xlC.rte version $INSTALLED_XLCPP_VERSION meets the requirement."
fi

# 22765: Verify if GNU Libc version is supported for Linux
# 26508: Support Debian
# DIST=`grep DISTRIB_ID /etc/*-release | awk -F '=' '{print $2}'`
if [ "$MY_PLATFORM" != "aix" ]; then
    DIST=`grep -w ID /etc/os-release | awk -F '=' '{print $2}'`
    # if [ "$DIST" != "Ubuntu" ]; then
    if [ "$DIST" != "ubuntu" -a "$DIST" != "debian" ]; then
        case "${SYSTEM_OS}" in
            Linux*)
                MINIMUM_SUPPORTED_GLIBC_VERSION=2.17 # The GLibc supported version is defined in APP v8.0 onwards
                GLIBC_VERSION=`ldd --version | awk '/ldd/{print $NF}'`
                GLIBC_VERSION="${GLIBC_VERSION/./}"
                GLIBC_VERSION="${GLIBC_VERSION//.*/}"
                if [ $GLIBC_VERSION -lt 217 ]
                then
                    echo "The GNU LIBC version is less than required \"$MINIMUM_SUPPORTED_GLIBC_VERSION\". Exit \""`basename "$0"`"\" now."
                    exit 1
                fi
                ;;
            *)
                ;;
        esac
    fi
fi

# Prepare packaged components
if [ -d "$APP_TMP" ]; then
    rm -rf "$APP_TMP"
fi
mkdir "$APP_TMP"

preparePackagedComponents RESULT JVM_HOME_RESULT
if [ "$RESULT" = "N" ] ; then
    echo "Error in preparing files, installer will terminate"
    rm -rf "$APP_TMP"
    exit 1
fi

# Backup user setting files
backupUserConfig "$TEMP_CONFIG_DIR"

# Move packaged components
if [ ! -d "$APP_HOME" ]; then
    mkdir "$APP_HOME"
fi
# 28798: Changed to use copy instead of move to overwrite app home contents
# mv "$APP_TMP"/* "$APP_HOME"
cp -rf "$APP_TMP"/* "$APP_HOME"
rm -rf "$APP_TMP"

# Verify if JVM home exist
cd "$APP_HOME"
JVM_HOME=$APP_HOME/jvm
if [ "$JVM_HOME_RESULT" = "N" ]; then
    USER_JVM_HOME=""
    echo "Please enter your java $JAVA_VERSION home: "
    read USER_JVM_HOME
    if [ -z "$USER_JVM_HOME" ]; then
        echo "Invalid java home!"
        exit 1
    fi
    if [ ! -d "$USER_JVM_HOME" ]; then
        echo "$USER_JVM_HOME does not exist!"
        exit 1
    fi
    JVM_SECURITY="$APP_HOME/util/jvm/lib/security"
    if [ -d "$JVM_SECURITY" ]; then
        echo "Copy java $JAVA_VERSION from $USER_JVM_HOME"
            if [ ! -d "$JVM_HOME" ]; then
                cp -rf "$USER_JVM_HOME" "$JVM_HOME"
            else
                cp -rf $USER_JVM_HOME/* $JVM_HOME
            fi
        cp -rf $JVM_SECURITY/* $JVM_HOME/lib/security
    else
        echo "Create symbolic link from $USER_JVM_HOME"
        ln -sf "$USER_JVM_HOME" "$JVM_HOME"
    fi
fi

# Do pre-processing
DEP_LIB_PATH=
if [ "$CLIENT_MAJOR_VERSION" = "$NEW_CLIENT_MAJOR_VERSION" ]; then
    # Set DEP_LIB_PATH
    . ./bin/getEnvInfo.sh
else
    # Set DEP_LIB_PATH
    SYSTEM_ARCH=`uname -m`

    OS_NAME=
    case "${SYSTEM_OS}" in
      Linux* )
        OS_NAME="Lin"
        ;;
      *BSD* )
        OS_NAME="Fbd"
        ;;
      SunOS )
        OS_NAME="Sos"
        SYSTEM_ARCH=`isainfo -b`
        ;;
      * )
        echo "OS \"${SYSTEM_OS}\" is not supported. Exit now."
        exit 1
        ;;
    esac

    OS_ARCH=
    if [ -z "${DEP_LIB_PATH}" ]; then
        case "${SYSTEM_ARCH}" in
            i[3-6]86 | 32)
                OS_ARCH="X86"
            ;;
            x86_64 | amd64 | 64)
                OS_ARCH="X64"
            ;;
            armv6*)
                OS_ARCH="Av6"
            ;;
            armv7*)
                OS_ARCH="Av7"
            ;;
            armv5*)
                OS_ARCH="Arm"
            ;;
            aarch64*)
                OS_ARCH="A64"
            ;;
            powerpc64)
                OS_ARCH="P64"
            ;;
            * )
                echo "Arch \"${SYSTEM_ARCH}\" is not supported. Exit now."
                exit 1
            ;;
        esac
        DEP_LIB_PATH=${OS_NAME}${OS_ARCH}
    fi
fi

JAVA_HOME="$APP_HOME/jvm"
JAVA_EXE="$JAVA_HOME/bin/java"

# Verify the JAVA_EXE whether it can be executed or not.
if [ ! -x "${JAVA_EXE}" ]
then
    echo "The Java Executable file \"${JAVA_EXE}\" cannot be executed. Exit \""`basename "$0"`"\" now."
    exit 1
fi

LD_LIBRARY_PATH="${APP_BIN}/${DEP_LIB_PATH}":".":"${LD_LIBRARY_PATH}"

SHLIB_PATH="$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH SHLIB_PATH

cd "${APP_BIN}"

# Reference path will be used to avoid empty space in the parent directory
LIB_HOME=.
CLASSPATH=
JAVA_OPTS=
if [ "$CLIENT_MAJOR_VERSION" = "$NEW_CLIENT_MAJOR_VERSION" ]; then
    JAVA_OPTS=$(grep -vE '^\s*#|^\s*$' cb.ini | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | tr '\n' ' ')
    CLASSPATH="$LIB_HOME:$LIB_HOME/cb.jar"
else
    # jdom is needed by v9 class path
    CLASSPATH="$LIB_HOME:$LIB_HOME/jdom-1.1.3.jar:$LIB_HOME/cb.jar"
fi

JNI_PATH="-Djava.library.path=$LIB_HOME:$LIB_HOME/${DEP_LIB_PATH}"
MAIN_CLASS=InstallerUtil

INSTALLER_MODE="-i"
PRODUCT_EDITION="obm"

echo "Running installer pre-processes."

# Do not include double-quote for java options, jni path, classpath,
# main class, installer mode, and product edition
# Only apply double-quote for app home
"${JAVA_EXE}" $JAVA_OPTS $JNI_PATH -cp $CLASSPATH $MAIN_CLASS $INSTALLER_MODE $PRODUCT_EDITION "${APP_HOME}"

# Install Application
TIMESTAMP_LOG=`date '+%y%m%d%H%M%S'`
INSTALL_LOG="$APP_HOME/install-$TIMESTAMP_LOG.log"
INSTALL_SCRIPT="$APP_BIN/install.sh"
if [ ! -f "$INSTALL_SCRIPT" ]; then
    echo "Install script not exist"
    exit 1
fi
echo "Install Application Path: $APP_HOME"
sh "$INSTALL_SCRIPT" "$PRIVILEGE_CHK" >> "$INSTALL_LOG"

# Restore user data files
restoreUserConfig "$TEMP_CONFIG_DIR"

# Fix file permission
CONFIG_SCRIPT="$APP_BIN/config.sh"
CONFIG_LOG="$APP_BIN/config.log"
if [ -f "$CONFIG_SCRIPT" ]; then
    sh "$CONFIG_SCRIPT" "FIX_PERMISSION" >> "$CONFIG_LOG"
fi

# Exit
echo "Done"
exit 0
