#!/bin/bash

#============================================================================
# Copyright 2009- ECMWF.
# This software is licensed under the terms of the Apache Licence version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction.
#============================================================================

# Environment variables from the configuration step
ECFLOWUI_BT=no
ECFLOWUI_BT_EMAIL_ADDRESS_FILE=x
ECFLOWUI_VERSION=
ECFLOWUI_INSTALLDIR=/usr
ECFLOWUI_USAGE_LOG=x
ECFLOWUI_SITE_TAG=x
PREDEF_SYSTEM_SERVERS_LIST=

#-----------------------------------------------------------
# The system server list
#-----------------------------------------------------------

export ECFLOW_SYSTEM_SERVERS_LIST=${ECFLOW_SYSTEM_SERVERS_LIST:=$PREDEF_SYSTEM_SERVERS_LIST}

#-----------------------------------------------------------
# Figure out the directory of the exe
#-----------------------------------------------------------

EXE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
exe=${EXE_DIR}/ecflow_ui.x


function failed() {
    local msg="Error: $1"
    echo $msg >&2
    exit 1
}

# ----------------------------------------------------------
# Clean up the tmp directory at the end or on error
#-----------------------------------------------------------
cleanup(){
    status=$?
    trap "" EXIT ERR
    set +e  # do not exit on errors during cleanup

    # kill all the child processes
    pkill -P $$ || true

    # restore stdout/stderr
    if [ x$ECFLOWUI_SLOG != xyes ]
    then
        exec 1>&5
        exec 2>&6
    fi

    if [ "$status" -eq "0" ]
    then
        echo "$(basename $0): $1 (OK) (line $2), exit status $status, starting 'cleanup'"
    else
        status_message="$(basename $0): $1 on ERROR (line $2), exit status $status, starting 'cleanup'"
        echo $status_message

        if [ -e $ECFLOWUI_LOGFILE ] ; then

            # if the error message is something that's not really a crash, then we should
            # not send a crash report
            hhh=$(grep "The X11 connection broke" $ECFLOWUI_LOGFILE)  # 0 if x11 broke, 1 if not
            x11notbroke=$?

            if [ "$x11notbroke" = "1" ] ; then

                TAILNUM=50
                UI_TAILNUM=50

                if [ $ECFLOWUI_BT != "no" ] ; then
                    # find the backtrace tag if there
                    btline=$(grep -n "Backtrace:" $ECFLOWUI_LOGFILE | cut -f1 --delimiter=':')
                    gret=$?
                    if [ "$gret" = "0" -a "x$btline" != "x" ] ; then
                        nlines=$(wc -l $ECFLOWUI_LOGFILE | cut -f1 --delimiter=' ')
                        TAILNUM=$(expr $nlines - $btline + 100)
                    fi
                fi


                # Logic: ECFLOWUI_BT_EMAIL_ADDRESS_FILE is not set, then the log/backtrace
                # will go to stdout; otherwise it will be e-mailed to the
                # addresses instead (the user will not see the backtrace).

                if [ $ECFLOWUI_BT_EMAIL_ADDRESS_FILE != "x" ] ; then
                    if [ -e $ECFLOWUI_BT_EMAIL_ADDRESS_FILE ] ; then
                        EFLOWUI_LOGTAIL="${ECFLOWUI_LOGFILE}.tail"
                        ecfuimsg="ecFlowUI backtrace from user $USER"
                        echo "Sending crash report by e-mail..."
                        echo "user/host          : $USER/$HOST"          >  $EFLOWUI_LOGTAIL
                        echo "ecflow version     : $ECFLOWUI_VERSION"    >> $EFLOWUI_LOGTAIL
                        echo "ecflow install dir : $ECFLOWUI_INSTALLDIR" >> $EFLOWUI_LOGTAIL
                        echo "start time         : $ECFLOWUI_STARTTIME"  >> $EFLOWUI_LOGTAIL
                        echo "stop time          : $(date)"              >> $EFLOWUI_LOGTAIL
                        echo ""                                          >> $EFLOWUI_LOGTAIL
                        echo $status_message                             >> $EFLOWUI_LOGTAIL
                        tail -$TAILNUM $ECFLOWUI_LOGFILE                 >> $EFLOWUI_LOGTAIL

                        #Add the last lines from the user interaction log file
                        if [ -e $ECFLOWUI_LOGFILE ] ; then
                            echo ""                                      >> $EFLOWUI_LOGTAIL
                            echo "Last $UI_TAILNUM lines of user interaction log file:" >> $EFLOWUI_LOGTAIL
                            tail -${UI_TAILNUM} $ECFLOWUI_LOGFILE     >> $EFLOWUI_LOGTAIL
                        fi

                        addr=$(head -1 $ECFLOWUI_BT_EMAIL_ADDRESS_FILE)
                        mail -s "$ecfuimsg"  $addr < $EFLOWUI_LOGTAIL
                        rm -f $EFLOWUI_LOGTAIL
                        echo "Report sent"
                    else
                        echo "No report sent because e-mail address file does not exist: $ECFLOWUI_BT_EMAIL_ADDRESS_FILE"
                    fi
                else
                    echo "Last $TAILNUM lines of log file:"
                    tail -$TAILNUM $ECFLOWUI_LOGFILE

                    #Add the last lines from the user interaction log file
                    if [ -e $ECFLOWUI_LOGFILE ] ; then
                        echo ""
                        echo "Last $UI_TAILNUM lines of user interaction log file:"
                        tail -${UI_TAILNUM} $ECFLOWUI_LOGFILE
                    fi
                fi
            else
                echo "X11 Connection broke - no report sent to developers"
            fi # $x11notbroke
        fi
    fi

    # remove temporary directory
    if [ $(echo $ECFLOWUI_TMPDIR | grep -c "/ecflow_ui.") -ge 1 ] ; then
        rm -Rf $ECFLOWUI_TMPDIR
    fi

    exit $status
}


#-----------------------------------------------------------
# checkoption()
# Checks the command-line options
#-----------------------------------------------------------

checkoption() {

    local USE_PC4=0
    local USE_CMD=0
    local CMD_MSG=""

    while [ "$1" != "" ]
    do
        case "$1" in

        -log)
            ECFLOWUI_SLOG=yes
            ;;

        -slog)
            ECFLOWUI_SLOG=yes
            ;;

        -s)
            export ECFLOWUI_SESSION_MANAGER=yes
            ;;

        -ts)
            export ECFLOWUI_TEMP_SESSION_HOST=$2
            export ECFLOWUI_TEMP_SESSION_PORT=$3
            if [ "x$ECFLOWUI_TEMP_SESSION_HOST" == x -o "x$ECFLOWUI_TEMP_SESSION_PORT" == x ] ; then
                failed "Please supply a host and port: ecflow_ui -ts <host> <port>"
            fi
            echo "Starting a temporary session: host=$ECFLOWUI_TEMP_SESSION_HOST, port=$ECFLOWUI_TEMP_SESSION_PORT"
            shift 2
            ;;

        -title)
            export ECFLOWUI_TITLE=$2
            shift
            ;;

        -fs)
            export ECFLOWUI_FONT_SIZE=$2
            shift
            ;;

        -pc4)
            ECFLOWUI_USER_START_CMD="proxychains4"
            CMD_MSG="Starting ecFlowUI with the following command: ${ECFLOWUI_USER_START_CMD}"
            USE_PC4=1
            ;;

        -cmd)
            ECFLOWUI_USER_START_CMD="$2"
            if [ "x${ECFLOWUI_USER_START_CMD}" == "x" ] ; then
                failed "No command is specified for option -cmd!"
            fi
            CMD_MSG="Starting ecFlowUI with user specified command: ${ECFLOWUI_USER_START_CMD}"
            USE_CMD=1
            shift
            ;;

        #Specify the location of the config dir
        -confd)
            export ECFLOWUI_CONFIG_DIR=$2
            if [[ $ECFLOWUI_CONFIG_DIR  != /* ]] ; then
                failed "Please specify an absolute path for flag -confd!"
            fi
            echo "Starting ecFlowUI with user specified config dir: ${ECFLOWUI_CONFIG_DIR}"
            shift
            ;;

        -h)
            ECFLOWUI_HELP=yes
            ;;

        esac
        shift
    done

    if [[ $USE_PC4 -eq 1 && $USE_CMD -eq 1 ]] ; then
        failed "The -pc4 and -cmd flags cannot be used together"
    elif [[  $USE_PC4 -eq 1 || $USE_CMD -eq 1 ]] ; then
        echo $CMD_MSG
    fi
}

#-----------------------------------------------------------
# Help message
#-----------------------------------------------------------

printhelp() { 

    version=$("$exe" --version 2>/dev/null)

    cat <<HEND
ecFlowUI $version
  Command-line flags:
    -fs               : set fontsize (in points) for the user interface
    -log              : write log messages to standard output
    -s                : start via the session manager
    -ts <host> <port> : start a temporary session viewing the given server
    -pc4              : start the executable via the proxychains4 command
    -cmd <cmd>        : start the executable via the specified command
    -confd <dir>      : start with the specified configuraton directory
    -h                : print this help message
HEND

cat << HEND

  Environment variables that have an effect on ecFlowUI:
  [current value in brackets]

  ECFLOW_SYSTEM_SERVERS_LIST   Pre-defined system server list files. User settings in
                               ecFlowUI (Preferences > Server > System server list) will overwrite it.
                               [$ECFLOW_SYSTEM_SERVERS_LIST]
HEND

}

checkoption "$@"

if [ "x$ECFLOWUI_HELP" != x ]
then
    printhelp
    exit 0
fi

#-----------------------------------------------------------
# usage log
#-----------------------------------------------------------

set +e  # failing to write to the log file should not cause a fatal error
if [ $ECFLOWUI_USAGE_LOG != x ]
then
	# checks on file existence and size
	if [ -f $ECFLOWUI_USAGE_LOG ]  # log file exists?
	then
		if [ ! -s $ECFLOWUI_USAGE_LOG ]  # file is empty? - write the header line
		then
			echo "date,time,version,user,host,site" >> $ECFLOWUI_USAGE_LOG
		fi

		echo "`date -u '+%Y.%m.%d,%R'`,$ECFLOWUI_VERSION,$USER,`hostname`,$ECFLOWUI_SITE_TAG" >> $ECFLOWUI_USAGE_LOG
	else
		echo "Log file $ECFLOWUI_USAGE_LOG does not exist."
	fi
fi
set -e


#Define tmp root dir
TMPDIR_ROOT=${TMPDIR:=/tmp}

# check that TMPDIR_ROOT actually exists - we can't run without it
if [ ! -d $TMPDIR_ROOT ]
then
    echo ""
    echo "  Temporary directory '$TMPDIR_ROOT' does not exist"
    echo "  ecFlowUI needs this in order to run. Check that environment"
    echo "  variable \$TMPDIR is set to a valid directory and try again."
    exit 1
fi

#Define and create tmp dir
export ECFLOWUI_TMPDIR=${TMPDIR_ROOT}/ecflow_ui.$$.$LOGNAME
mkdir -p $ECFLOWUI_TMPDIR

#Check if we could create it
if [ $? -ne 0 ]
then
    echo ""
    echo "  Temporary directory '$ECFLOWUI_TMPDIR' could not be created."
    echo "  ecFlowUI needs this in order to run. Check that environment"
    echo "  variable \$TMPDIR is set to a valid directory and try again."
    exit 1
fi


# Where to write the log file to
export git=$ECFLOWUI_TMPDIR/ecflowui_log_$$.$LOGNAME.txt

# Where to write the user interaction log file to
export ECFLOWUI_LOGFILE=$ECFLOWUI_TMPDIR/ecflowui_uilog_$$.$LOGNAME.txt

#---------------------------------------------------------------
# Create socket dir for local domain socket based communication
#---------------------------------------------------------------

export ECFLOWUI_SOCKETDIR=$ECFLOWUI_TMPDIR/sockets
mkdir -p $ECFLOWUI_SOCKETDIR

#---------------------------------------------------------------
# Manage config dir.
# From version 5.3.0 onwards the default config
# dir is: ${HOME}/.ecflow_ui_v5.
# Previously it was: ${HOME}/.ecflow_ui
#---------------------------------------------------------------

confDirDefault="${HOME}/.ecflow_ui_v5"
confDir=${confDirDefault}
confDir_v4="${HOME}/.ecflow_ui"

# if default the config dir does not exist we try to copy it
# from an existing one
if [[ ! -d "${confDir}" ]] ; then
    export ECFLOWUI_CONFIG_DIR_COPIED=1
    # the user did not start ecFlowUI with the -confd option and the
    # old confdir exists
    if  [[ x"${ECFLOWUI_CONFIG_DIR}" == x && -d "${confDir_v4}" ]] ; then
        cp -Rf "${confDir_v4}" "${confDir}"
        #  the session description is not copied over
        session_json="${confDir}/default.session/session.json"
        if [[ -f "${session_json}" ]] ; then
            rm -f "${session_json}"
        fi
    fi
fi

#---------------------------------------------------------------
# Remove lock files created more than 3 s ago (see ECFLOW-980)
#---------------------------------------------------------------

confDir=${ECFLOWUI_CONFIG_DIR:=${confDirDefault}}
#We are extra careful an delete the files in a loop instead of using exec for find
if [[ -d $confDir ]] ; then
    for fn in $(find $confDir -type f -mmin +1 -name "*.lock") ; do
        if [[ $fn == *.lock ]] ; then
            echo "Remove lock file: ${fn}"
            rm -f $fn
        fi
    done
fi
#-----------------------------------------------------------
# Close tty and redirect stdout to a file?
#-----------------------------------------------------------

if [ x$ECFLOWUI_SLOG != xyes ]
then
    exec  < /dev/null
    exec 5>&1                 # store for later
    exec 6>&2                 # store for later 
    exec 1> $ECFLOWUI_LOGFILE # (restored in cleanup())
    exec 2>&1                 # redirect stderr to stdout, (restored in cleanup())
    # note that it seems to be better to do
    #   exec 2>&1
    # rather than 
    #   exec 2> $ECFLOWUI_LOGFILE
    # because this way we get the stderr at the end rather than the start
    # due to the difference in flushing behaviours
fi



# =============================================================
# tmp directory cleaned automatically at end or at error.
# on new platforms check that these signals are valid:

ECFLOWUI_SIGLIST="QUIT TERM XCPU  XFSZ"
#              3    15   30/24 31/25

trap 'cleanup "EXIT" $LINENO' EXIT
trap 'cleanup "SIGNAL trap" $LINENO' $ECFLOWUI_SIGLIST

# note when we started it up
ECFLOWUI_STARTTIME=$(date)

#-----------------------------------------------------------
# The log viewer exe
#-----------------------------------------------------------

ECFLOWUI_LOG_VIEWER=${EXE_DIR}/ecflow_ui_log.x

#-----------------------------------------------------------
# Set up environment on mac
#-----------------------------------------------------------

if [[  $(uname | tr '[:upper:]' '[:lower:]') == "darwin" ]]; then
    export QT_MAC_WANTS_LAYER=1
fi

#-----------------------------------------------------------
# Run the executable
#-----------------------------------------------------------

if [[ ${ECFLOWUI_USER_START_CMD} = "proxychains" || ${ECFLOWUI_USER_START_CMD} = "proxychains"[4-9] ]] ; then
    export ECFLOWUI_USE_PROXYCHAINS=1
fi

#-----------------------------------------------------------
# Backtrace report?
#-----------------------------------------------------------

if [ $ECFLOWUI_BT != "no" ]
then
    catchsegv ${ECFLOWUI_USER_START_CMD} "$exe"
else
    ${ECFLOWUI_USER_START_CMD} "$exe"
fi

