#!/bin/bash

# Copyright (C) 2005 - 2017  Eric Van Dewoestine
#
# 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, see <http://www.gnu.org/licenses/>.

if [ "$(whoami)" == "root" ] ; then
  echo "eclimd should not be run as root."
  echo "You need to run eclimd as the same user as your editor (vim, emacs, etc)."
  exit 1
fi

usage(){
  echo "Usage: eclimd [eclimopt ...] [jvmarg ...]"
  echo "  Note: the following eclim options, if supplied, must precede any jvmargs, etc."
  echo "  -b/--background  start eclimd in the background."
  echo "  -d/--debug       enable eclimd's debug logging."
  echo "  -f/--file <file> specify the location of an eclimrc file other than the"
  echo "                   default (~/.eclimrc). Must be the first option supplied."
  echo ""
  echo "Note: eclimd also supports running the eclipse garbage collector to"
  echo "      to remove stale bundles after upgrades, etc.:"
  echo "  $ eclimd gc"
}

if [ "$1" = "-?" -o "$1" = "-h" -o "$1" = "--help" ] ; then
  usage
  exit 0
fi

if [ -z "$JAVA" ] ; then
  JAVA=$(which java 2> /dev/null)
  if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/bin/java" ] ; then
      JAVA="$JAVA_HOME/bin/java"
    elif [ -x "$JAVA_HOME/jre/bin/java" ] ; then
      JAVA="$JAVA_HOME/jre/bin/java"
    fi
  fi
  JAVA_VERSION=$(
    $JAVA -version 2>&1 |
      grep version |
      perl -pe 's|.*"[0-9]\.(.*)\..*".*|\1|'
  )
fi

if [ -z "$JAVA" ] ; then
  echo "Unable to locate your java install."
  echo "Please set your JAVA_HOME environment variable or"
  echo "set JAVA to the location of your java executable."
  exit 1
fi

##
# Determines eclim's home directory and sets the ECLIM_HOME var to that path.
#
resolve_eclim_home(){
  FILEPATH="$0"

  # handle symlink to eclimd script
  # readlink -f is easier, but not supported on mac or bsd
  while [ -h "$FILEPATH" ] ; do
    PREV=$FILEPATH
    FILEPATH=`readlink "$FILEPATH"`
    if [ -z "$FILEPATH" -o "$FILEPATH" = "$PREV" ] ; then
      FILEPATH=$PREV
      break
    fi

    # handle relative symlinks (neither eclim build nor installer create these,
    # so must have been created by the user or 3rd party installer)
    if [ ! -f "$FILEPATH" ] ; then
      PREVDIR=`dirname "$PREV"`
      FILEPATH=$PREVDIR/$FILEPATH
    fi
  done

  CURPATH=`dirname "$FILEPATH"`
  ECLIM_HOME=`cd "$CURPATH/.." ; pwd`
}

##
# Determines the eclipse home path and the eclipse launcher jar and sets
# ECLIM_ECLIPSE_HOME and ECLIPSE_LAUNCHER to those results.
#
resolve_eclipse_launcher(){
  ECLIM_ECLIPSE_HOME="/opt/eclipse-java"
  if [ -z "$ECLIM_ECLIPSE_HOME" -o ! -d "$ECLIM_ECLIPSE_HOME" ]; then
    ECLIM_ECLIPSE_HOME=`cd "$ECLIM_HOME/../../"; pwd`
  fi

  # Find the least modified launcher.
  ECLIPSE_LAUNCHER=`find "$ECLIM_ECLIPSE_HOME/plugins" \
    -name 'org.eclipse.equinox.launcher_*.jar' -exec ls -1t "{}" + | head -n1`

  if [ ! -e "$ECLIPSE_LAUNCHER" ]; then
    echo "Unable to locate the eclipse launcher jar." 1>&2
    exit 1
  fi
}

##
# Builds a list of vm args to be passed to eclipse and sets ECLIM_VMARGS
# accordingly.
#
build_vmargs(){
  #ECLIMD_OPTS="-Djava.ext.dirs"
  if [ -n "$ECLIMD_OPTS" ] ; then
    ECLIM_VMARGS=("${ECLIM_VMARGS[@]}" "$ECLIMD_OPTS")
  fi

  # attempt to grab properties from .eclimrc if available.
  PERL=`which perl 2> /dev/null`
  if [ -f "$ECLIMRC" -a -n "$PERL" ] ; then
    IFS=$'\n'
    for vmarg in $(cat "$ECLIMRC" | perl -pe '
        # remove leading/trailing whitespace
        s|^\s+||g ; s|\s+$|\n|g ;
        # delete comment lines
        s|^#.*$||g ;
        # delete empty lines
        s|^\n||g ;
        # remove line continuations
        s|\\\\\n||g ;
        # add -D for each property
        s|^\s*([a-zA-Z])|-D\1|g ;
      ')
    do
      arg=$(echo "$vmarg" | perl -pe 's|(-D.*?)=.*|\1|')
      arg=$(echo "$arg" | perl -pe 's|\d+.*||')
      if [[ "${ECLIM_VMARGS[@]}" != *"$arg"* ]] ; then
        ECLIM_VMARGS=("${ECLIM_VMARGS[@]}" $vmarg)
      fi
    done
  fi

  # ensure that the correct jvm environment is used, but only force the
  # architecture if we find the swt jars, since linux distros may have the swt
  # libraries outside of eclipse.
  SWT=`ls $ECLIM_ECLIPSE_HOME/plugins/org.eclipse.swt.*.jar 2> /dev/null`
  if [ -n "$SWT" ] ; then
    if `echo "$SWT" | grep -q "x86_64"` ; then
      ARCH=-d64
    else
      ARCH=-d32
    fi

    if ! `$JAVA $ARCH -version 2> /dev/null` ; then
      echo "Your jvm does not support the architecture required " \
        "for the version of eclipse you have installed: $ARCH"
      exit 1;
    fi
    ECLIM_VMARGS=($ARCH "${ECLIM_VMARGS[@]}")
  fi

  ECLIPSE_INI="$ECLIM_ECLIPSE_HOME/eclipse.ini"
  if `uname -a | grep -iq "darwin"` ; then
    ECLIPSE_INI="$ECLIM_ECLIPSE_HOME/Eclipse.app/Contents/Eclipse/eclipse.ini"
  fi

  # add any eclipse vmargs not present
  if [ -f "$ECLIPSE_INI" -a -n "$PERL" ] ; then
    CONTENTS=$(cat "$ECLIPSE_INI" | perl -pe 's|\n| |g')
    IFS=$'\n'
    IS_VMARGS=0
    for line in $(cat "$ECLIPSE_INI") ; do
      if [[ $IS_VMARGS -ne 1 ]] ; then
        if [[ "$line" == "-vmargs"* ]] ; then
          IS_VMARGS=1
        fi
        continue
      fi

      vmarg=$line
      arg=$(echo "$vmarg" | perl -pe 's|(-D.*?)=.*|\1|')
      arg=$(echo "$arg" | perl -pe 's|\d+.*||')
      # ignore dock icon since it's probably on OSX and relative to
      # Eclipse.app/Contents
      if [[ "$vmarg" == *-Xdock:icon* ]] ; then
        continue
      fi
      # ignore java 9 options if the current env is running a lower java
      # version.
      if [[ "$JAVA_VERSION" < "9" ]] ; then
        if [[ "$vmarg" == *--add-modules* ]] ; then
          continue
        fi
        if [[ "$vmarg" == *--permit-illegal-access* ]] ; then
          continue
        fi
      fi
      if [[ "${ECLIM_VMARGS[@]}" != *"$arg"* ]] ; then
        ECLIM_VMARGS=("${ECLIM_VMARGS[@]}" $vmarg)
      fi
    done
  fi

  # set a default for max heap space
  if [[ "${ECLIM_VMARGS[@]}" != *-Xmx* ]]; then
    ECLIM_VMARGS=("${ECLIM_VMARGS[@]}" -Xmx256m)
  fi

  # for osx
  if `uname -a | grep -iq "darwin"` ; then
    if [[ "${ECLIM_VMARGS}[@]" != *-XstartOnFirstThread* ]]; then
      ECLIM_VMARGS=("${ECLIM_VMARGS[@]}" -XstartOnFirstThread)
    fi
  fi
}

APPLICATION=org.eclim.application
ECLIMRC=$HOME/.eclimrc

DEBUG=0
BACKGROUND=0
while true ; do
  case "$1" in
    -d | --debug )
      DEBUG=1; shift ;;
    -b | --background )
      BACKGROUND=1; shift ;;
    -f | --file )
      if [ -f "$2" ] ; then
        ECLIMRC="$2"
      elif [ -z "$2" -o "${2:0:1}" = '-' ] ; then
        echo "please supply the path to the eclimrc file to load"
        exit 1
      else
        echo "file not found: $2"
        exit 1
      fi
      shift
      shift
      ;;
    gc )
      APPLICATION=org.eclipse.equinox.p2.garbagecollector.application
      shift ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

resolve_eclim_home
resolve_eclipse_launcher

declare -a ECLIM_VMARGS=("$@")
build_vmargs
if [ $DEBUG -eq 1 ] ; then
  ECLIM_VMARGS=("${ECLIM_VMARGS[@]}" -Dorg.eclim.debug)
fi

ARGS=(
  "${ECLIM_VMARGS[@]}"
  -jar
  "$ECLIPSE_LAUNCHER"
  --launcher.suppressErrors
  -debug
  -clean
  -refresh
  -application $APPLICATION
)

if [ $BACKGROUND -eq 1 ]; then
  CLASSPATH="" $JAVA "${ARGS[@]}" > /dev/null &
else
  echo $JAVA -version
  $JAVA -version
  echo "JAVA_VERSION=$JAVA_VERSION"
  echo ""
  echo $JAVA "${ARGS[@]}"
  CLASSPATH="" $JAVA "${ARGS[@]}"
fi
