#!/bin/sh

################################################################################
# Copyright (C) 2010-2013 NICE s.r.l.
# All Rights Reserved
#
# This software is the confidential and proprietary information
# of NICE s.r.l. ("Confidential Information").
# You shall not disclose such Confidential Information
# and shall use it only in accordance with the terms of
# the license agreement you entered into with NICE.
################################################################################


# Get absolute path. Use it inside a subshell
get_abs_path() {
    cd "$1"
    pwd
}


# Escape an SH string to be suitable to an eval inside a single quote.
# Arguments:
# 1) the string to escape (mandatory)
#
sh_escape() {
    printf '%s' "$1" | sed "s/'/'\"'\"'/g;"
}


# Print an error message to stderr and exit.
# Arguments:
# 1) the error message string (mandatory)
# 2) the exit code (default: 1)
#
die() {
    echo "$1" >&2
    if [ -n "$2" ]; then
        exit "$2"
    else
        exit 1
    fi
}


# Check if a directory is valid.
# Arguments:
# 1) the directory
# 2) a short description of the directory
#
check_dir() {
    if [ -z "$1" ]; then
        return 1
    fi

    if [ ! -d "${1}" ]; then
        die "Detected directory for $2 (${1}) is not valid, please check your configuration"
    fi
}


# Check if a file exists and is executable.
# Argument:
# 1) the file to check
#
check_executable() {
    if [ -z "$1" ]; then
        return 1
    fi
    
    if [ ! -e "${1}" ]; then
        die "No such file: ${1}"
    fi

    if [ ! -x "${1}" ]; then
        die "File is not executable: ${1}"
    fi
    return 0
}


# Print a debug message, if debug is enabled.
# Arguments:
# 1) the message to print
#
debug() {
    if [ -n "${DEBUG}" ]; then
        echo "$1" >&2
    fi
}


# Print DCV execution environment, if debug is enabled.
#
debug_print_dcv_env() {
    if [ -z "${DEBUG}" ]; then
        return
    fi
    
    echo 'Execution environment (DCV specific variables):' >&2
    env \
    | sed -n -e '
        /^RVN_/ {
            bprint
        }
        /^DCV_/ {
            bprint
        }

        bend

        :print
        s/^/  /p
        bend

        :end
        ' >&2
}



# ---[ MAIN ]---------------------------------------------------------------- #


# Get the OS name
_uname=`uname`

# Get the architecture
_arch=`uname -m`


# Reset environment
_args=''
_dry_run=0
_connection_file=''

# Parsing command line arguments.
# Plese note: this is not a complete parsing, since we are searching these options everywhere... we assume we never had
# an option value starting with --. The alternative is provide a FULL command line parsing for all possible options of
# vncviewer program.
#
while [ -n "$1" ]; do
    case "$1" in
        --fps)
            export RVN_SHOW_FPS=1
            ;;
        --verbose)
            export DCV_VERBOSE=1
            DEBUG=1
            ;;
        --dry-run)
            _dry_run=1
            ;;
        *)
            _opt_shsafe=`sh_escape "$1"`
            if [ -r "${1}" -a -z "${_connection_file}" ]; then
                _connection_file="${1}"
                # -config is not mandatory, but if we do not specify it
                # vncserver gets things wrong when there is a proxy since
                # it tries to see if the host specified in the file is
                # reachable and if it isn't it does not consider it a file
                _args="${_args} -config '${_opt_shsafe}'"
            else
                _args="${_args} '${_opt_shsafe}'"
            fi
            ;;
    esac
    shift
done


debug "OS name: ${_uname}"
debug "Architecture: ${_arch}"

_dir=`readlink -f "${0}" 2> /dev/null`

if [ "$?" = "0" ]; then
    _dir=`dirname "${_dir}"`
else
    # OS X (and BSD) does not have readlink -f, so for now we do not support symlinks
    _dir=`dirname "${0}"`
fi

# Check .vnc configuration file and retrieve proxy settings if defined
if [ -n "${_connection_file}" ]; then
    _proxy_type=`grep -i ^ProxyType "${_connection_file}" | cut -d= -f 2 | sed 's/ //g' 2>/dev/null`
    echo "${_proxy_type}" | grep -i socks >/dev/null 2>&1
    if [ $? -eq 0 ]; then
        export DCV_PROXY_TYPE=SOCKS5
    fi
    _proxy_server=`grep -i ^ProxyServer "${_connection_file}" | cut -d= -f 2 | cut -d: -f 1 | sed 's/ //g' 2>/dev/null`
    if [ -n "${_proxy_server}" ]; then
        export DCV_PROXY_SERVER="${_proxy_server}"
    fi
    _proxy_port=`grep -i ^ProxyServer "${_connection_file}" | cut -d= -f 2 | cut -d: -f 2 | sed 's/ //g' 2>/dev/null`
    if [ -n "${_proxy_port}" ]; then
        export DCV_PROXY_PORT="${_proxy_port}"
    fi
fi

# Fix configuration based on OS
case "${_uname}" in

    [Ll]inux)
        # This tool is installed under DCV_ROOT
        export DCV_ROOT=`get_abs_path "${_dir}"`
        check_dir "${DCV_ROOT}" 'DCV_ROOT'

        # Get lib and bin directory based on DCV_ROOT and current system architecture
        if [ "${_arch}" = 'x86_64' ]; then
            _bin_dir="${DCV_ROOT}/RealVNC/vnc64/"
            _lib_dir="${DCV_ROOT}/lib64/"
        else
            _bin_dir="${DCV_ROOT}/RealVNC/vnc/"
            _lib_dir="${DCV_ROOT}/lib/"
        fi

        check_dir "${_bin_dir}" 'binaries'
        check_dir "${_lib_dir}" 'libraries'

        _vncviewer_program="${_bin_dir}/vncviewer"

        if [ ! -r "${_lib_dir}/librvn_receiver.so" ]; then
            die 'Cannot find the librvn library. Check your installation...'
        fi

        export PATH="${_bin_dir}:${PATH}"
        debug "Adding directory to PATH: ${_bin_dir}"

        export LD_LIBRARY_PATH="${_lib_dir}:${LD_LIBRARY_PATH}"
        debug "Adding path for libraries: ${_lib_dir}"

        ;;


    [Dd]arwin)

        # The path of this script is e.g. /Applications/DCV.app/Contents/MacOS/<this_script>

        # Export the DCV_ROOT as the 'Contents' directory
        export DCV_ROOT=`get_abs_path "${_dir}/../Resources"`
        check_dir "${DCV_ROOT}" 'DCV_ROOT'

        _lib_dir="${DCV_ROOT}/lib"
        check_dir "${_lib_dir}" 'libraries'

        if [ ! -r "${_lib_dir}/librvn_receiver.dylib" ]; then
            die 'Missing librvn_receiver under lib directory'
        fi

        bundle_res="${DCV_ROOT}"
        bundle_lib="$bundle_res"/lib
        bundle_bin="$bundle_res"/bin
        bundle_data="$bundle_res"/share
        bundle_etc="$bundle_res"/etc

        export DYLD_LIBRARY_PATH="${bundle_lib}:${_lib_dir}:${DYLD_LIBRARY_PATH}"
        debug "DYLD_LIBRARY_PATH: ${DYLD_LIBRARY_PATH}"

        export XDG_CONFIG_DIRS="$bundle_etc:$XDG_CONFIG_DIRS"
        export XDG_DATA_DIRS="$bundle_data:$XDG_DATA_DIRS"
        export GTK_DATA_PREFIX="$bundle_res"
        export GTK_EXE_PREFIX="$bundle_res"
        export GTK_PATH="$bundle_res"
        export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-3.0/gdk-pixbuf.loaders"
        export GIO_EXTRA_MODULES="$bundle_lib/gio/modules"
        export PANGO_LIBDIR="$bundle_lib"
        export PANGO_SYSCONFDIR="$bundle_etc"

        # The vncviewer program is under Contents/MacOS directory and it's called vncviewer
        _vncviewer_program="${_dir}/vncviewer"

        ;;


    *)
        die "Unsupported OS: ${_uname}"
        exit 1
        ;;

esac

debug "VNCviewer program: ${_vncviewer_program}"

debug_print_dcv_env


check_executable "${_vncviewer_program}"


# We want to always add -FullColour
_args="-FullColour ${_args}"


_vncviewer_program=`sh_escape "${_vncviewer_program}"`

if [ -n "$DEBUG" ]; then
    echo "Executing '${_vncviewer_program}' ${_args}" >&2
fi

debug "Dry run: ${_dry_run}"
if [ "${_dry_run}" != 1 ]; then
    eval "'${_vncviewer_program}' ${_args}"
    _exit_code="$?"
else
    _exit_code=0
fi

debug "Exit code: ${_exit_code}"


exit "${_exit_code}"


# --------------------------------------------------------------------------- #
# ex: set ts=4 sw=4 et syntax=sh :
# --------------------------------------------------------------------------- #

