#!/bin/bash

bold=$(tput bold)
underline=$(tput smul)
normal=$(tput sgr0)

echoerr() {
    cat <<< "$@" 1>&2
}

# error message function (nested exit):
trap "exit 1" TERM
export ARBINST_SCRIPT_PID=$$
err() {
    echoerr "Error in `basename $0`:"
    echoerr "${bold}  $@${normal}"
    echoerr "Please fix and then rerun script!"
    kill -s TERM $ARBINST_SCRIPT_PID
}

separator() {
    echo ''
}

separator
echo "${bold}${underline}Welcome to the ARB Package${normal}"

test -z "${BASH_VERSINFO}" && separator && err "Please call this script using 'bash arb_install.sh'"

elim_invalid_chars() {
    local FILE="${1}"
    # remove some characters really unwanted in paths:
    FILE=${FILE// /}
    FILE=${FILE//\'/}
    FILE=${FILE//\"/}
    FILE=${FILE//\`/}
    echo ${FILE}
}

DL_DIR=$(pwd)
DL_NS=$(elim_invalid_chars "${DL_DIR}")

if [ ! "$DL_NS" = "$DL_DIR" ]; then
    separator
    if [ ! "$DL_NS" = "" ]; then
        echo "Note: the path '$DL_NS' would be ok.."
    fi
    err "Your download directory '$DL_DIR' contains invalid characters."
fi

cont() {
    echo "Warning: $@" 1>&2
    echo "${bold}Do you want to continue [y]${normal}"
    read var
    case "$var" in
        n) err "Script aborted by user" ;;
        *) echo 'Continuing...' ;;
    esac
}

untar() {
    local TGZ="$1"; shift

    # remove old DEPOT BUG
    rm -f DEPOT/gde/bin

    if [ ! -r "${TGZ}" ]; then
        err "Cannot find or read file '${TGZ}'"
    fi
    if gunzip --stdout "${TGZ}" | tar xfv -; then
        echo ">>> ${TGZ} uncompressed and untared"
        if [ ! -e bin/arb_ntree ]; then
            err "bin/arb_ntree not found (wrong archive?)"
        fi
        if [ ! -x bin/arb_ntree ]; then
            err "bin/arb_ntree not executable (wrong archive?)"
        fi
    else
        err "Failed to uncompress/untar '${TGZ}'"
    fi
}

arb_realpath() {
    # replacement for 'realpath'
    #
    # Note: this function is duplicated in SH/arb_path.sh@arb_realpath
    local FILE="$1"; shift

    local REALPATH=$(realpath    "$FILE" 2>/dev/null )
    local READLINK=$(readlink -f "$FILE" 2>/dev/null )

    if [ -z "${REALPATH}" ]; then
        if [ -z "${READLINK}" ]; then
            echoerr "Warning: neighter realpath nor readlink works here"
            if [ -e "${FILE}" ]; then
                local PWDFILE="$(pwd)/${FILE}"
                if [ -e "${PWDFILE}" ]; then echo "${PWDFILE}"
                else echo "${FILE}"
                fi
            else echo "${FILE}"
            fi
        else echo "${READLINK}"
        fi
    else
        if [ -z "${READLINK}" ]; then echo "${REALPATH}"
        else
            if [ "${READLINK}" != "${REALPATH}" ]; then
                echoerr "Warning: realpath and readlink differ (REALPATH=${REALPATH} READLINK=${READLINK})"
            fi
            echo "${REALPATH}"
        fi
    fi
}

# --------------------------------------------------
# detect input archives:

separator

ARB_TGZ=
SINA_TGZ=

for TGZ in arb*.tgz; do
    NOSINA=${TGZ%-sina-fat.tgz}
    if [ "${NOSINA}" = "$TGZ" ]; then
        if [ -z "${ARB_TGZ}" ]; then
            ARB_TGZ="${TGZ}"
        else
            echo "Found two arb archives:"
            ls -al -h "${ARB_TGZ}" "${TGZ}"
            echo ""
            err "cannot decide which to use. Please remove one of these!"
        fi
    else
        if [ -z "${SINA_TGZ}" ]; then
            SINA_TGZ="${TGZ}"
        else
            echo "Found two sina archives:"
            ls -al -h "${SINA_TGZ}" "${TGZ}"
            echo ""
            err "cannot decide which to use. Please remove one of these!"
        fi
    fi
done

if [ -n "${SINA_TGZ}" ]; then
    SINA_TGZ=$(arb_realpath "${SINA_TGZ}")
    echo "Detected sina tarball: ${SINA_TGZ}"
fi

if [ -z "${ARB_TGZ}" ]; then
    echo "For available arb versions please refer to"
    echo "    http://bugs.arb-home.de/wiki#ARBversions"
    separator
    err "No arb tarball found in `pwd`"
fi
ARB_TGZ=$(arb_realpath "${ARB_TGZ}")
echo "Detected arb  tarball: ${ARB_TGZ}"

# --------------------------------------------------
# general instructions + ask for destination:

separator
echo '  Note:   - You may abort this script with ctrl-"C"'
echo '          - You can rerun this script as often as you like'
echo '          - Old ARB data will be kept if requested (in this case'
echo '            you can simply change some options)'
echo '          - Pressing <return> will select the value in brackets'
separator
echo "${underline}Please answer some questions:${normal}"
separator
echo 'Where would you like to install ARB?'
echo '  ARB is not a single program but a set of programs, datafiles ...'
echo '  To install ARB, all files will be stored in a single directory.'
separator
echo '  This script will create that directory, copy all needed files and'
echo '  sets permissions correctly.'
separator
echo '  Please note that you will need write permission at the destination.'
separator
if [ "$EUID" -ne 0 ]; then
    # normal user
    ARBHOMED=${HOME}/arb
    echo '  - to install ARB inside your home directory, enter "'${ARBHOMED}'"'
    echo '  - otherwise press Ctrl-C now to abort installation and'
    echo '    rerun this script using:'
    echo '        sudo bash arb_install.sh'
else
    # root user
    ARBHOMED=/usr/arb
    echo '  - to install ARB for all users, enter "'${ARBHOMED}'"'
fi
separator

if [ "$ARBHOME" != "" ]; then
    if test -f $ARBHOME/lib/arb_tcp.dat; then
        echo "  Note: There seems to be an existing arb installation at"
        echo "        ${ARBHOME}"
        separator
    fi
fi

echo "${bold}Enter full installation path: [${ARBHOME:-${ARBHOMED}}]${normal}"
read ARBHOMEI
separator

if [ "$ARBHOMEI" = "" ]; then
    ARBHOME="${ARBHOME:-${ARBHOMED}}";
else
    ARBHOME="${ARBHOMEI}";
fi

# check for some really unwanted characters in path:
AH_NS=$(elim_invalid_chars ${ARBHOME})
if [ ! "$AH_NS" = "$ARBHOME" ]; then
    separator
    if [ ! "$AH_NS" = "" ]; then
        echo "Note: the path '$AH_NS' would be ok.."
    fi
    err "The specified path '$ARBHOME' contains invalid characters."
fi

ARBHOME=$(arb_realpath "${ARBHOME}")

# --------------------------------------------------
# handle existing arb installation:

if test -d $ARBHOME; then
    if test -w $ARBHOME; then
        separator
        echo 'The destination directory'
        echo "    $ARBHOME"
        echo 'already exists!'

        if [ -z "$(ls -A ${ARBHOME})" ]; then
            echo "Note: directory is empty and will be used for arb installation."
        else
            ARB_TCP_BAK=arb_tcp_`date +%Y%m%d`.dat
            if [ ! -e ${ARB_TCP_BAK} -a -e $ARBHOME/lib/arb_tcp.dat ]; then
                echo '[creating backup copy of arb_tcp.dat in download directory]'
                cp $ARBHOME/lib/arb_tcp.dat ${ARB_TCP_BAK}
            fi

            echo '  You may now'
            echo '  * either delete the old arb directory completely'
            echo '  * or only update/change options of the old version.'
            echo "${bold}Delete old directory? (y/n)[n]${normal}"
            read delete_dir
            echo
            case "$delete_dir" in
                y)
                    if rm -r $ARBHOME/* ;then
                        echo ">>> all data in $ARBHOME deleted"
                    else
                        cont "failed to delete files in $ARBHOME"
                    fi
                    ;;
                *)
                    if test -f $ARBHOME/lib/arb_tcp.dat; then
                        bckup=$ARBHOME/lib/arb_tcp.dat.`date +%y%m%d%H%M%S`
                        echo ">>>old $ARBHOME/lib/arb_tcp.dat found"
                        echo ">>>backup to $bckup"
                        cp $ARBHOME/lib/arb_tcp.dat $bckup
                    fi
                    echo ">>> old data not deleted";;
            esac
        fi
    else
        err "directory exists and is not writable";
    fi
else
    if mkdir -p $ARBHOME; then
        echo ">>> $ARBHOME created"
    else
        err "cannot create directory $ARBHOME";
    fi
fi

cd $ARBHOME
ARBHOME=`pwd`

if [ -d lib/pictures ]; then
    separator
    echo "${underline}Old ARB package found${normal} (type n to change only some options)."
    echo "${bold}  Do you want to update the old package? (y/n)[y]${normal}"
    read var;
    case "$var" in
        n)
            echo "Old version unchanged"
            ;;
        *)
            echo "updating ARB";
            untar "${ARB_TGZ}"
            ;;
    esac
else
    untar "${ARB_TGZ}"
fi

# --------------------------------------------------
# configure ptserver:

separator
echo "${underline}Specify PT_SERVER files location${normal}"
echo '  ARB needs a writeable directory to store the pt_server files. '
echo '  Those files are needed for fast database search'
echo '  (by probe_design, probe_match and the automatic aligner)'
echo '  and need a lot of disc space (up to several 100 mega bytes,'
echo '  e.g. 4000 16S RNA sequences require about 40 MB).'
echo '  This files are not created now. They can be build by any user via'
echo '          <ARB/Probes/PT_SERVER Admin/Build server>'
echo '  You may define a special directory as the pt_server files location.'
echo '  This prevents any loss of data installing a new version of '
echo '  ARB. '

echo 'Where do you want to put your pt_server data'
echo '          1. <CR> - (new installation of ARB)'
echo '                    for placing pt_server data within ARB directory tree'
echo '                    (Default location).'
echo '                  - (updating ARB)'
echo '                    using the previous location'
echo '          2. "Path" to link pt_server data directory to'
echo "              (if you choose this option you won't loose your PT-Servers when doing future software updates)"
echo "${bold}Enter path:${normal}"
read pt_dir
echo
case "$pt_dir" in
    "")
        echo "installing the pt_server data in $ARBHOME/lib/pts"
        if test -h ${ARBHOME}/lib/pts ; then
            echo "Are you sure to delete "
            echo ">>> pt_server files at non default location:"
            ls -ld ${ARBHOME}/lib/pts
        else
            if test -d ${ARBHOME}/lib/pts; then
                echo ">>> pt_server files at default location: unchanged"
            else
                (cd lib;rm -f pts;mkdir pts;)
            fi
        fi;;
    *)
        echo "changing your pt_server file location"
        if test -h ${ARBHOME}/lib/pts; then
            echo ">>> non default location found: removing old link"
            rm lib/pts
        else
            if test -d ${ARBHOME}/lib/pts; then
                echo ">>> data in default location found"
                echo "${bold}Do you want to remove old ptserver data (recommended)? [y]${normal}"
                read ANSWER
                case "$ANSWER" in
                    n) echo 'data not deleted' ;;
                    *) rm -r lib/pts
                       echo 'data deleted' ;;
                esac
            fi
        fi
        if test ! -d $pt_dir; then
            echo ">>> Creating special PT_SERVER directory $pt_dir"
            if mkdir -p $pt_dir; then
                echo ">>> $pt_dir created"
            else
                err "Couldn't create $pt_dir"
            fi
        fi
        (cd lib;ln -s $pt_dir pts;)
esac

separator
echo 'Who is responsible for the PT_SERVER index files?'
echo '  Answer  y: if you trust your users (less administration; recommended)'
echo '          n: if PT_SERVER files shall only be changable by administrator'
echo '  or simply press return to keep the settings of an old installation.'
echo "${bold}Should everybody be allowed to build/update PT_SERVER files? (y/n/dont_change)[dont_change]${normal}"
read var
echo
case "$var" in
    y)
        echo ">>> all users are allowed to update the PT_SERVER";
        chmod 777 lib/pts
        chmod 666 lib/pts/* 2>/dev/null ;;
    n)
        echo ">>> only `whoami` is allowed to update the pt_server";
        chmod 755 lib/pts
        chmod 644 lib/pts/* 2>/dev/null ;;
    *)
        echo ">>> permissions of lib/pts remain unchanged";;
esac

# --------------------------------------------------
# configure nameserver:

separator
echo "${underline}NameServer installation${normal}"
echo '  The NameServer is a program, that synchronizes all species names'
echo '  of the databases of different users.'
echo '  Users that import foreign data into their database and want to'
echo '  export those data to other ARB users should be allowed to change'
echo '  the names file in $ARBHOME/lib/nas/names.dat'
echo '  Answer  y: if all users may import foreign databases'
echo '          n: if there are some mean untrusty users'
echo '  or simply press return to keep the old settings'
echo "${bold}Do you trust your users? (y/n/dont_change)[dont_change]${normal}"
read var
echo
case "$var" in
    y)
        echo ">>> all user are allowed to change the names file";
        chmod 777 lib/nas
        chmod 666 lib/nas/*;;
    n)
        echo ">>> only `whoami` is allowed to change the names file ${ARBHOME}/lib/nas/names.dat"
        chmod 755 lib/nas
        chmod 644 lib/nas/*;;
    *)
        echo ">>> permissions of lib/nas remain unchanged";;
esac

# --------------------------------------------------
# setup arb_tcp.dat:

separator
echo "${underline}Networking${normal}"
echo '  To speed up calculation one special host can be assigned as'
echo '  the PT_SERVER host. That means that all database search is done'
echo '  on that host. This saves computer resources as different users'
echo '  may share one server.'
echo '  To get the best results this host "H" should:'
echo '                  1.      be fast,'
echo '                  2.      have a lot of real memory (>=64 meg),'
echo '                  3.      have a lot of swap space (>=400 meg),'
echo '                  4.      allow all users to run "ssh H ...",'
echo '                  5.      contain the discs with the PT_SERVER files.'

echo '  n       You want to assign a special Network host'
echo '  s       You have a Stand alone computer'
if test "X$bckup" != "X"; then
    echo '  o       Use information of already installed ARB'
    echo "${bold}Choose (s/n/o)[s]${normal}"
else
    echo "${bold}Choose (s/n)[s]${normal}"

fi
read var
echo


case "$var" in
    o)
        mv $bckup lib/arb_tcp.dat;
        echo ">>> old lib/arb_tcp.dat restored";;
    n)
        separator
        echo "Enter the name of your host for the pt_server"
        read host
        echo "Checking connection to $host"
        if ssh $host ls >/dev/zero; then
            echo ">>> ssh $host ok"
        else
            err ">>> cannot run 'ssh $host'";
        fi
        rm -f lib/arb_tcp.dat;
        cat lib/arb_tcp_org.dat |sed -e "/localhost\:/$host\:/g" >lib/arb_tcp.dat
        echo ">>> server installed";;
    *)
        cp lib/arb_tcp_org.dat lib/arb_tcp.dat
        echo ">>> server installed";;
esac

# --------------------------------------------------
# install sina:

separator
echo "${underline}SINA integration${normal}"
if [ -n "${SINA_TGZ}" ]; then
    echo "Detected sina archive: ${SINA_TGZ}"
    if [ -x bin/sina ]; then
        echo "Note: The installed arb already seems to contain sina."
        echo "      => will not install another sina!"
    else
        INSTALL_SINA=0
        HAVE_SINA=0
        # check for installation via SH/arb_sina_install_from_fat_tarball.sh
        if [ -d bin/fatsina ]; then
            echo "Note: there is already another sina installed from a tarball."
            HAVE_SINA=1
            echo "${bold}  Do you want to update the sina installation? (y/n)[y]${normal}"
        else
            echo "${bold}  Do you want to install sina into arb? (y/n)[y]${normal}"
            INSTALL_SINA=1
        fi

        read var;
        case "$var" in
            n)
                if [ ${HAVE_SINA} = 1 ]; then
                    echo "Old sina version unchanged."
                else
                    echo "Will not install sina."
                fi
                ;;

            *)
                if [ ${HAVE_SINA} = 1 ]; then
                    echo "updating SINA from ${SINA_TGZ}";
                    SH/arb_sina_install_from_fat_tarball.sh UNINSTALL "${ARBHOME}"
                else
                    echo "installing SINA from ${SINA_TGZ}";
                fi
                SH/arb_sina_install_from_fat_tarball.sh "${SINA_TGZ}" "${ARBHOME}"
                ;;
        esac
    fi
else
    if [ ! -x bin/sina ]; then
        if [ ! -d bin/fatsina ]; then
            echo "No sina installed with arb."
            echo "Hint: the installation script will attempt to install sina for you,"
            echo "      if you download an arb-XXX-fat-sina.tgz and"
            echo "      save it into ${DL_DIR}"
        fi
    fi
fi

# --------------------------------------------------
# finish + print instructions for setup

separator
echo "${bold}>>> ARB installation completed${normal}"

separator
SHELL_ANS=0

echo "${underline}Finally, you have to tell your system where to find arb${normal}"
echo "First find out which shell you are using, by opening a new terminal window and typing"
echo '        echo $SHELL'
echo ""
echo "Depending on what is your shell there are several choices:"
echo ""
echo "    1. Change your local .profile or .bashrc (if you are using ksh/bash, which"
echo "                                              is the default shell for Linux)"
echo "    2. Change your local .cshrc file         (if you are using csh/tcsh)"
echo "    3. Create an alias for arb               (any shell)"
echo "    4. I don't want to edit anything         (any shell)"
echo ""

echo "${bold}Enter (1,2,3 or 4) to achieve further installation instructions:${normal}"

while [ "$SHELL_ANS" = "0" ]; do

    read var

    separator
    case "$var" in
        1)
            echo '******************************************************';
            echo "${bold}add the following lines to your ~/.profile${normal}";
            echo "${bold}or to your ~/.bashrc for bash-users${normal}";
            echo '******************************************************';
            echo "     ARBHOME=$ARBHOME;export ARBHOME";
            echo '     LD_LIBRARY_PATH=${ARBHOME}/lib:${LD_LIBRARY_PATH}';
            echo '     export LD_LIBRARY_PATH';
            echo '     PATH=${ARBHOME}/bin:${PATH}';
            echo '     export PATH';
            separator
            echo 'enter the following command:';
            echo '     . ~/.profile'
            SHELL_ANS=1
            ;;
        2)
            echo '******************************************';
            echo "${bold}add the following lines to your ~/.cshrc${normal}";
            echo '******************************************';
            echo "     setenv ARBHOME $ARBHOME";
            if test "X${LD_LIBRARY_PATH}" != "X"; then
                echo '     setenv LD_LIBRARY_PATH $ARBHOME/lib\:$LD_LIBRARY_PATH';
            else
                echo '     setenv LD_LIBRARY_PATH $ARBHOME/lib';
            fi
            echo '     setenv PATH $ARBHOME/bin\:$PATH';
            separator
            echo 'enter the following command:';
            echo '     source ~/.cshrc'
            SHELL_ANS=1
            ;;
        3)
            echo '**************************************************';
            echo "${bold}add one of the following lines to your init file${normal}";
            echo '**************************************************';
            echo "# bash users add to ~/.bashrc:";
            echo "  alias arb=$ARBHOME/bin/arb";
            echo "# tcsh users add to ~/.cshrc:";
            echo "  alias arb '$ARBHOME/bin/arb'";
            SHELL_ANS=1
            ;;
        4)
            echo "Note: You will need to specify the full path to start arb.";
            SHELL_ANS=2
            ;;
        *)
            echo 'wrong answer'
            ;;
    esac
done

if [ "$EUID" -eq 0 ]; then
    # only shown to root user:
    separator
    echo "${underline}Note for sysadmins:${normal}"
    echo "     In order to provide arb for all users, edit one or several"
    echo "     of the global shell init files in /etc (e.g. /etc/bash.bashrc)"
    echo "     in the same manner as described above for the"
    echo "     local shell init files."
    separator
    echo "     Note for unintended sysadmins:"
    echo "         To edit the global bash init file use e.g."
    echo "             sudo nano /etc/bash.bashrc"
    echo "         Insert the 'arb' alias on a separate line."
fi
separator
echo "Please read the files"
echo "  $ARBHOME/arb_INSTALL.txt"
echo "  $ARBHOME/arb_UBUNTU.txt    (if you're using ubuntu)"
echo "about additional libraries and tools needed by ARB."
separator
echo "After you have installed everything and performed the changes to your init file,"
echo "open a new terminal window and start arb by typing"
separator
if [ $SHELL_ANS = 2 ]; then
    echo "     $ARBHOME/bin/arb";
else
    echo "     arb"
fi
separator
echo "${bold}Have much fun using ARB${normal}"
echo "ARB Team <arb@arb-home.de>"
separator

