#!/bin/bash
#
# gvSIG. Desktop Geographic Information System.
#
# Copyright (C) 2007-2013 gvSIG Association.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301, USA.
#
# For any additional information, do not hesitate to contact us
# at info AT gvsig.com, or visit our website www.gvsig.com.
#

# gvSIG.sh

#
# Notes:
# - find command in busybox (win32) don't support "-exec"
# - trap command in busybox (win32) don't support "trap comando ERR"
# - busybox (win32) don't support statement "local"
# - Careful with loop "while", changes in variables within the loop are
#   lost when you leave this.  Use "for" loops to avoid this.
# - busybox (win32) don't support typeset
#

#set -x
set -e

ARGS="$@" # Can't use ${@/ , use ${ARGS/ instead

#if [ "$BASH_VERSION" = "" ] ; then
#    echo "gvSIG.sh is not running with a bash shell"
#    if type bash 2>/dev/null ; then
#        echo "Relaunch gvSIG.sh with a bash shell."
#        exec bash $@
#    else
#        echo "Can't locate a bash, continue the execution with current shell."
#    fi
#fi

onerror() {
  set +x
  echo "Error executing the command:"
  echo ">>> $BASH_COMMAND <<<"
  echo "At line $BASH_LINENO"
  exit 1
}
#trap onerror ERR

####################
# Identify OS and Architecture  #
####################

UNAME=$(uname -m -o -s | tr '[:upper:]' '[:lower:]')
# Use -s to identify cygwin
case "$UNAME" in
*cygwin*|*mingw64_nt*)
    # gvSIG installation folder
    export GVSIG_INSTALL_FOLDER=$($CYGPATH -am "$PWD")
    # gvSIG home folder
    export HOME=$($CYGPATH -am "$USERPROFILE")
    OS="win"
    ARG_D32=""
    CPSEP=";"
    CYGWIN="yes"
    CYGPATH="$PWD/cygpath.exe"
    CYGCHECK="$PWD/cygcheck.exe"
    # In developmen mode with cywin installed ?
    test -f "$CYGPATH" || CYGPATH=$(type -P cygpath)
    test -f "$CYGCHECK" || CYGCHECK=$(type -P cygcheck)
    ;;
*darwin*)
    OS="darwin"
    ARG_D32=""
    CPSEP=":"
    CYGWIN="no"
    ;;
*win*)
    OS="win"
    ARG_D32=""
    CPSEP=";"
    CYGWIN="no"
    CYGPATH="./cygpath -am"
    CYGCHECK="./cygcheck.exe"
    ;;
*lin*)
    OS="lin"
    # Only linux support -d32 arg
    ARG_D32="-d32"
    CPSEP=":"
    CYGWIN="no"
    ;;
*)
    OS="unknown"
    ARG_D32=""
    CPSEP=":"
    CYGWIN="no"
    ;;
esac

case "$UNAME" in
*x86_64*)
    ARCH="x86_64"
    ;;
*amd64*)
    ARCH="x86_64"
    ;;
*)
    ARCH="x86"
    ;;
esac


if [ "${OS}" == "win" ] ; then
  if [ "$CYGWIN" = "yes" ] ; then
    xmkdir() {
      if [ "$1" == "-p" ] ; then
        # La criatura falla si intentamos hacer algo como:
        #   mkdir c:/algo1/algo2
        #   mkdir /cygdrive/c/algo1/algo2
        # Lo primero nos aseguramos que el path esta en el formato
        # que esperamos, el de windows "C:/algo1/algo2"
        # luego hacemos un:
        #   cd /cygdrive/c
        # Y por ultimo un:
        #   mkdir -p algo1/algo2
        xmkdir_path=$($CYGPATH -am "$2")
        if [ "${xmkdir_path:1:2}" == ":/" ] ; then
          cd "/cygdrive/${xmkdir_path:0:1}"
          if mkdir -p "${xmkdir_path:3}" ; then
            cd - >/dev/null
          else
            cd - >/dev/null
            false
          fi
        else
          mkdir -p "$2"
        fi
      else
        mkdir "$1"
      fi
    }
  else
    xmkdir() {
      if [ "$1" == "-p" ] ; then
        # La criatura falla si intentamos hacer algo como:
        #   mkdir c:/algo1/algo2
        # Asi que primero hacemos un:
        #   cd c:/
        # Y luego un:
        #   mkdir -p algo1/algo2
        #
        if [ "${2:1:2}" == ":/" ] ; then
          cd "${2:0:3}"
          if mkdir -p "${2:3}" ; then
            cd - >/dev/null
          else
            cd - >/dev/null
            false
          fi
        else
          mkdir -p "$2"
        fi
      else
        mkdir "$1"
      fi
    }
  fi
else
  xmkdir() {
    mkdir "$@"
  }
fi


########################

getJavaArchitecture() {
	if [ "$ARCH" = "x86" ] ; then
                # Si la arquitectura del SO es x86 decimos
                # que la de java es x86
		echo "x86"
	else
                # si la arquitectura es x86_64, comprobamos
                # la arquitectura de la java que nos pasan
		if "$1" -version 2>&1 | egrep -i "64-Bit" >/dev/null ; then
			echo "x86_64"
		else
			echo "x86"
		fi
	fi
}

#################################
# Set install and home folders  #
#################################

# Go into the gvSIG installation folder, just in case
x=$(dirname "$0")
cd "$x"

if [ "$GVSIG_APPLICATION_NAME" = "" ] ; then
  GVSIG_APPLICATION_NAME=gvSIG
fi
export GVSIG_APPLICATION_NAME

# gvSIG installation and home folder
if [ "$CYGWIN" = "yes" ] ; then
  # gvSIG installation folder
  export GVSIG_INSTALL_FOLDER=$($CYGPATH -am "$PWD")
  # gvSIG home folder
  export HOME=$($CYGPATH -am "$USERPROFILE")
else
  # gvSIG installation folder
  export GVSIG_INSTALL_FOLDER="$PWD"
  # gvSIG home folder
  if [ "$OS" = "win" ] ; then
    # https://redmine.gvsig.net/redmine/issues/4033
    export HOME="$USERPROFILE"
  fi
fi
export GVSIG_HOME_FOLDER="$HOME/$GVSIG_APPLICATION_NAME"

####################
# Load config file #
####################

update_user_preferences() {
  if [ "$GVSIG_HOME_FOLDER" = "$GVSIG_INSTALL_FOLDER/preferences" ] ; then
    # It is a portable using the installation preferences folder as the user preferences folder.
    # We do not do anything.
    return
  fi
  if [ ! -d "$GVSIG_INSTALL_FOLDER/preferences" ] ; then
    # There is no installation preference folder. We do not do anything.
    return
  fi
  
  echo "Updating preferences in personal folder..."
  echo "This may take a moment."
  
  if [ ! -d "$GVSIG_HOME_FOLDER" ] ; then
    # There is no folder with the gvSIG preferences in the user's folder. 
    # We copy the preferences folder of the gvSIG installation.
    echo "Copying the default gvSIG preferences to the user's folder."
    xmkdir -p "$GVSIG_HOME_FOLDER"
    cp -a "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME" "$GVSIG_HOME_FOLDER/.."
    echo "Updating preferences finished."
    return
  fi
  # The user already has their preferences in their personal folder.
  # We check if we have to copy some preferences that do not have:
  # - Preferences of some plugin that does not have
  # - Missing symbols
  # - Scripts

  #
  # Check if some plugin preferences are missing, and copy them
  if [ -d  "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins" ] ; then
    cd "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins"
    for FOLDER in *
    do
      if [ -d "$FOLDER" -a ! -d "$GVSIG_HOME_FOLDER/plugins/$FOLDER" ] ; then
        echo "Copying the default $FOLDER preferences to the user's folder."
        xmkdir -p "$GVSIG_HOME_FOLDER/plugins/$FOLDER"
        cp -a "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/$FOLDER" "$GVSIG_HOME_FOLDER/plugins"
      fi
    done
  fi
  
  #
  # Check if any symbols are missing and copy them
  if [ -d "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/org.gvsig.app.mainplugin/Symbols" ] ; then
    cd "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/org.gvsig.app.mainplugin/Symbols"
    for FOLDER in *
    do
      if [ -d "$FOLDER" -a ! -d "$GVSIG_HOME_FOLDER/plugins/org.gvsig.app.mainplugin/Symbols/$FOLDER" ] ; then
        echo "Copying the default $FOLDER symbol to the user's folder."
        xmkdir -p "$GVSIG_HOME_FOLDER/plugins/org.gvsig.app.mainplugin/Symbols/$FOLDER"
        cp -a "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/org.gvsig.app.mainplugin/Symbols/$FOLDER" "$GVSIG_HOME_FOLDER/plugins/org.gvsig.app.mainplugin/Symbols"
      fi
    done
  fi
  
  #
  # Check if any script are missing and copy them
  if [ -d  "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/org.gvsig.scripting.app.mainplugin/scripts/addons" ] ; then
    cd "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/org.gvsig.scripting.app.mainplugin/scripts/addons"
    for FOLDER in *
    do
      if [ -d "$FOLDER" -a ! -d "$GVSIG_HOME_FOLDER/plugins/org.gvsig.scripting.app.mainplugin/scripts/addons/$FOLDER" ] ; then
        echo "Copying the default $FOLDER script to the user's folder."
        xmkdir -p "$GVSIG_HOME_FOLDER/plugins/org.gvsig.scripting.app.mainplugin/scripts/addons/$FOLDER"
        cp -a "$GVSIG_INSTALL_FOLDER/preferences/$GVSIG_APPLICATION_NAME/plugins/org.gvsig.scripting.app.mainplugin/scripts/addons/$FOLDER" "$GVSIG_HOME_FOLDER/plugins/org.gvsig.scripting.app.mainplugin/scripts/addons"
      fi
    done
  fi
  echo "Updating preferences finished."
}


if [ -f "$GVSIG_INSTALL_FOLDER/gvSIG.config" ] ; then
  . "$GVSIG_INSTALL_FOLDER/gvSIG.config"
fi
if [ -f "$GVSIG_HOME_FOLDER/gvSIG.config" ] ; then
  . "$GVSIG_HOME_FOLDER/gvSIG.config"
fi

update_user_preferences

if [ ! -d "$GVSIG_HOME_FOLDER" ] ; then
  xmkdir -p "$GVSIG_HOME_FOLDER"
fi

#################
# Logger config #
#################

LOGGER_FILE="$GVSIG_HOME_FOLDER/${GVSIG_APPLICATION_NAME}-launcher.log"
echo > "$LOGGER_FILE"

CONSOLELOGGER=true
if [ "${ARGS/*--consolelogger=false*/--consolelogger=false}" == "--consolelogger=false" ] ; then
    CONSOLELOGGER=false
fi

logger () {
  # level (INFO/WARNIG) message
  LOGGER_LEVEL="$1"
  shift
  if [ "$CONSOLELOGGER" == "true" ] ; then
    echo "$LOGGER_LEVEL launch $@"
  fi
  echo "$LOGGER_LEVEL launch $@" >> "$LOGGER_FILE"
}

logger_info () {
  logger "INFO" "$@"
}

logger_warn () {
  logger "WARNING" "$@"
}

logger_cmd() {
  logger_info "$@"
  if [ "$CONSOLELOGGER" == "true" ] ; then
    eval $@ 2>&1 | tee -a  "$LOGGER_FILE"
  else
    eval $@ 2>&1 > "$LOGGER_FILE"
  fi
}

logger_info "gvSIG Installation folder: $GVSIG_INSTALL_FOLDER"
logger_info "gvSIG home folder: $GVSIG_HOME_FOLDER"

##########################################################
# Search in gvSIG/extensiones the architecture of plugins
# installeds and set as PREFERED_ARCHITECTURE
# Note: Busybox in windows don't support -exec in find
##########################################################

setPreferedArchitecture() {
  pf_foundArch=""
  pf_fname=""
  cd "$GVSIG_INSTALL_FOLDER"
  find . -name package.info 2>/dev/null | while read pf_fname
  do
    cat "$pf_fname"
  done | grep "architecture=[^a]" | sort | head -n 1 | read pf_foundArch || true
  # El comando "read x" de la linea anterior puede fallar si
  # no hay ningun plugin depdendiente de la arquitectura, por eso
  # el "|| true" del final.
  if [ "X${pf_foundArch}X" != "XX" ] ; then
	  eval $pf_foundArch
	  PREFERED_ARCHITECTURE="$architecture"
  else
	  PREFERED_ARCHITECTURE="$ARCH"
  fi
  cd - >/dev/null
}

setPreferedArchitecture

##########################################################

export JAVA_HOME
export JAVA
export FORCE_JAVA_32BITS

FORCE_JAVA_32BITS=""
JAVA_HOME_OTHER_ARCHITECTURE=""

# PRIVATE JAVA HOMEs
if [ -d "$GVSIG_INSTALL_FOLDER/gvSIG/extensiones/jre" ] ; then
    PJH1="$GVSIG_INSTALL_FOLDER/gvSIG/extensiones/jre"
else
    PJH1=
fi
#
# El ls|head casca en win10 64 bits. Parece que hay algun problema con los
# pipes y el find y el ls.
if [ "${OS}" == "win" ] ; then
  PJH2=""
  PJH3=""
  PJH4=""
  PJH5=""
else
  PJH2=$(ls -dt "$GVSIG_HOME_FOLDER/jre/"*1.8* 2>/dev/null | head -1)
  PJH3=$(ls -dt "$GVSIG_HOME_FOLDER/jre/"*1.7* 2>/dev/null | head -1)
  PJH4=$(ls -dt "$GVSIG_HOME_FOLDER/jre/"*1.6* 2>/dev/null | head -1)
  PJH5=$(ls -dt "$GVSIG_HOME_FOLDER/jre/"*1.5* 2>/dev/null | head -1)
fi
if [ -d /usr/lib/jvm ] ; then
    PJH6=$(find /usr/lib/jvm -maxdepth 1 ! -name "jvm" -name "[a-zA-Z]*" ! -type l -print)
else
    PJH6=
fi

if [ -f "$PJH1/bin/java" ] ; then
    if [ ! -x "$PJH1/bin/java" ] ; then
	chmod a+x "$PJH1/bin/java"
    fi
fi

#
#
# Try to use java from:
# 1. Java in gvSIG/extensiones/jre (jre plugin)
# 2. Java specified in JAVA_HOME variable
# 3. Java in the HOME/gvsig/jre folder (old gvsig versions optionally create during installation process)
# 4. Java installed in the system (/usr/lib/jvm)
# 5. Java in the system path.
#
for JAVA_HOME_TO_USE in "$PJH1" "$JAVA_HOME" "$PJH2" "$PJH3" "$PJH4" "$PJH5" $PJH6 ""
do
  if [ "$JAVA_HOME_TO_USE" = "" ] ; then
	  continue
  fi
  logger_info "Located possible jre at: ${JAVA_HOME_TO_USE}"
done

for JAVA_HOME_TO_USE in "$PJH1" "$JAVA_HOME" "$PJH2" "$PJH3" "$PJH4" "$PJH5" $PJH6 ""
do
        if [ "$JAVA_HOME_TO_USE" = "" ] ; then
                continue
        fi
	logger_info "Checking JAVA_HOME ${JAVA_HOME_TO_USE}..."
        if [ ! -d "$JAVA_HOME_TO_USE" ] ; then
                logger_warn "Folder not found ($JAVA_HOME_TO_USE), skip"
                continue
        fi
        if [ ! -x "$JAVA_HOME_TO_USE/bin/java" ] ; then
                logger_warn "Not a valid JAVA_HOME ($JAVA_HOME_TO_USE), bin/java not found, skip"
                continue
        fi
	JAVA_ARCH=$(getJavaArchitecture "$JAVA_HOME_TO_USE/bin/java")
	if [ "$JAVA_ARCH" != "$PREFERED_ARCHITECTURE" ] ; then
                JAVA_HOME_OTHER_ARCHITECTURE="$JAVA_HOME_TO_USE"
                logger_warn "Prefered architecture is $PREFERED_ARCHITECTURE, java $JAVA_ARCH found in $JAVA_HOME_TO_USE, skip"
                continue
        fi
        break
done

if [ "$JAVA_HOME_TO_USE" = "" ] ; then
        # Try to use the java in the system path
        if ! type java >/dev/null ; then
                # java not found in the system path
                if [ "$JAVA_HOME_OTHER_ARCHITECTURE" != "" ] ; then
                        JAVA_HOME="$JAVA_HOME_OTHER_ARCHITECTURE"
                        JAVA="$JAVA_HOME/bin/java"
                        logger_warn "java $PREFERED_ARCHITECTURE not found in the system path, using $JAVA_HOME_OTHER_ARCHITECTURE"
                else
                        logger_warn "java not found in the system"
                        exit 1
                fi
        else
		if [ "$(getJavaArchitecture $(type -p java))" != "$PREFERED_ARCHITECTURE" ] ; then
                      logger_warn "java $PREFERED_ARCHITECTURE not found, using $(type -p java)"
                fi
                unset JAVA_HOME
                JAVA="java"
        fi
else
        JAVA_HOME="$JAVA_HOME_TO_USE"
        JAVA="$JAVA_HOME/bin/java"
fi

if [ "$PREFERED_ARCHITECTURE" = "x86" ] ; then
	FORCE_JAVA_32BITS="$ARG_D32"
else
	FORCE_JAVA_32BITS=""

fi
logger_info "Using java " $(type -p "$JAVA")

###################################################################
# gvSIG native libraries location
###################################################################

export GVSIG_NATIVE_LIBS=""
export LD_LIBRARY_PATH
export DYLD_LIBRARY_PATH
export PATH
export GVSIG_PROPERTIES=""

add_library_path() {
  #logger_info "add_library_path $1"
  GVSIG_NATIVE_LIBS="$1${CPSEP}$GVSIG_NATIVE_LIBS"

  # On Linux family systems
  LD_LIBRARY_PATH="$1${CPSEP}$LD_LIBRARY_PATH"
  # On Darwin family systems
  DYLD_LIBRARY_PATH="$1${CPSEP}$DYLD_LIBRARY_PATH"
  # On Windows family systems
  if [ "$CYGWIN" = "yes" ] ; then
    PATH="/cygdrive/${1/:/}:$PATH"
  else
    PATH="$1${CPSEP}$PATH"
  fi

}

list_shared_library_dependencies() {
  logger_info "Checking shared library dependencies for $1"
  case "$OS" in
  "win")
        logger_cmd "$CYGCHECK" "\"$1\""
        ;;
  "lin")
        logger_cmd ldd "\"$1\""
        ;;
  "darwin")
        logger_cmd otool -L "\"$1\""
        ;;
  esac || logger_warn "Problens checking shared library $1"  || true
}

add_classpath() {
  GVSIG_CLASSPATH="$GVSIG_CLASSPATH${CPSEP}$1"
}

add_property() {
  value="\"$2\""
  GVSIG_PROPERTIES="$GVSIG_PROPERTIES -D$1=$value"
}


###################################################################
# gvSIG java libraries location
###################################################################

# Load gvSIG Andami jars and dependencies for the classpath
for i in "$GVSIG_INSTALL_FOLDER/lib/"*.jar ; do
  if [ "$i" != "$GVSIG_INSTALL_FOLDER/lib/*.jar" -a "$i" != "" ]; then
    add_classpath "$i"
  fi
done
for i in "$GVSIG_INSTALL_FOLDER/lib/"*.zip ; do
  if [ "$i" != "$GVSIG_INSTALL_FOLDER/lib/*.zip" -a "$i" != "" ]; then
    add_classpath "$i"
  fi
done

# gvSIG Andami launcher

if [ "$GVSIG_LAUNCHER" = "" ] ; then
  GVSIG_LAUNCHER=org.gvsig.andamiupdater.Updater
fi
if [ "$GVSIG_PARAMS" = "" ] ; then
  GVSIG_PARAMS="$GVSIG_APPLICATION_NAME gvSIG/extensiones $@"
fi

export GVSIG_LAUNCHER
export GVSIG_PARAMS

########################
# Memory configuration #
########################

# Initial gvSIG memory (M=Megabytes, G=Gigabytes)
export GVSIG_INITIAL_MEM=${GVSIG_INITIAL_MEM:-256M}
# Maximum gvSIG memory (M=Megabytes, G=Gigabytes)
export GVSIG_MAX_MEM=${GVSIG_MAX_MEM:-1024M}
# Maximum permanent memory size: needed to load classes and statics
# A partir de java 1.8 ya no esta soportada esta opcion
#export GVSIG_MAX_PERM_SIZE=${GVSIG_MAX_PERM_SIZE:-128M}
#  -XX:MaxPermSize=${GVSIG_MAX_PERM_SIZE} 
#


#############################
# Execute plugin's autorun  #
#############################

for PLUGIN_FOLDER in "$GVSIG_INSTALL_FOLDER/gvSIG/extensiones/"* "$GVSIG_HOME_FOLDER/installation/gvSIG/extensiones/"*
do
  if [ -f "$PLUGIN_FOLDER/autorun.sh" ] ; then
    logger_info "Running autorun from plugin " $(basename "$PLUGIN_FOLDER")
    . "$PLUGIN_FOLDER/autorun.sh"
    cd "$GVSIG_INSTALL_FOLDER"
  fi
done

if [ "$OS" = "win" ] ; then
	add_library_path "$GVSIG_INSTALL_FOLDER"
fi

logger_info "LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
logger_info "PATH=$PATH"

#####################
# Java debug mode ? #
#####################

if [ "${ARGS/*--pause*/--pause}" == "--pause" ] ; then
    DEBUG_PAUSE="y"
else
    DEBUG_PAUSE="n"
fi

if [ "${ARGS/*--debug*/--debug}" == "--debug" ] ; then
  DEBUG_OPTIONS="-agentlib:jdwp=transport=dt_socket,address=8765,server=y,suspend=$DEBUG_PAUSE"
else
  DEBUG_OPTIONS=""
fi

########################
# Remove old log files #
########################

rm -f "${GVSIG_HOME_FOLDER}/gvSIG.log"*

################
# Launch gvSIG #
################

launch_gvSIG() {
    cd "$GVSIG_INSTALL_FOLDER"
    # For Java parameters documentation and more parameters look at:
    # http://download.oracle.com/javase/6/docs/technotes/tools/windows/java.html
    # http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
    CMD="\"${JAVA}\" \
      $GVSIG_CUSTOM_FONTS \
      $FORCE_JAVA_32BITS \
      -Xms${GVSIG_INITIAL_MEM} \
      -Xmx${GVSIG_MAX_MEM} \
      ${DEBUG_OPTIONS} \
      -Djava.library.path=\"${GVSIG_NATIVE_LIBS}\" \
      ${GVSIG_PROPERTIES} \
      -cp \"${GVSIG_CLASSPATH}\" \
      ${GVSIG_JAVA_PARAMS} \
      ${GVSIG_LAUNCHER} ${GVSIG_PARAMS}"

    logger_info Launching gvSIG: "${CMD}"
    eval "$CMD"
}

if [ "${ARGS/*--lib*/--lib}" != "--lib" ] ; then
    launch_gvSIG
fi

