#!/bin/bash -e

source $OPENSHIFT_CARTRIDGE_SDK_BASH

JBOSSEAP_BIN_DIR=${OPENSHIFT_JBOSSEAP_DIR}/bin
JBOSSEAP_PID_FILE=${OPENSHIFT_HOMEDIR}/app-root/runtime/jbosseap.pid
JBOSSEAP_DEPLOYMENTS_DIR=${OPENSHIFT_JBOSSEAP_DIR}/standalone/deployments
SCANCONFIG=""

source $JBOSSEAP_BIN_DIR/util

cartridge_type="jbosseap"

# Return the deployment-scanner configuration
function getscanconfig() {
    count=0
    while [ ${count} -lt 4 ]; do
      controller="${OPENSHIFT_JBOSSEAP_IP}:${OPENSHIFT_JBOSSEAP_MANAGEMENT_NATIVE_PORT}"
      scanconfig=`jboss-cli.sh -c --controller=${controller} "/subsystem=deployment-scanner/:read-resource(recursive=true)" 2>&1 || :`
      if [[ $scanconfig =~ '"outcome" => "success"' ]] ; then
        SCANCONFIG=$scanconfig
        return
      fi
      let count+=1

      sleep 2
    done
}

# Verify that the deployment scanner has finished running
function waitondeployments() {
    if ! ismgmtup; then
      client_message "Timed out waiting for management listening port"
      client_message "Could not connect to JBoss management interface, skipping deployment verification"
    else
      getscanconfig

      if [ "$SCANCONFIG" == "" ]; then
        client_message "Could not connect to JBoss management interface, skipping deployment verification"
      elif [[ $SCANCONFIG =~ '"scan-enabled" => true' ]]; then
        pushd $JBOSSEAP_DEPLOYMENTS_DIR

        artifacts=()
        while read -r -d $'\0'; do
          artifacts+=("$REPLY")
        done < <(find . -iregex '.*\.\([ejrsw]ar\|zip\)$' -print0)

        deployexploded=false
        if [[ $SCANCONFIG =~ '"auto-deploy-exploded" => true' ]]; then
          deployexploded=true
        fi
        deployarchive=false
        if [[ $SCANCONFIG =~ '"auto-deploy-zipped" => true' ]]; then
          deployarchive=true
        fi

        artifactsdeployed=()
        artifactsfailed=()
        artifactsskipped=()
        artifactsunknown=()
        for artifact in ${artifacts[*]}; do
          if ( [ -f $artifact ] && $deployarchive ) || ( [ -d $artifact ] && $deployexploded ); then
            # TODO triple check this logic, add a timeout 
            while [ -f ${artifact}.isdeploying ]; do
              client_message "Artifact: ${artifact} is still deploying"
              sleep 10
            done

            if [ -f ${artifact}.deployed ]; then
              artifactsdeployed+=($artifact)
            elif [ -f ${artifact}.failed ]; then
              artifactsfailed+=($artifact)
            else
              artifactsunknown+=($artifact)
            fi

          else
            # artifact skipped because of deployment scanner config
            artifactsskipped+=($artifact)
          fi
        done

        popd

        if [ ${#artifactsskipped[@]} -gt 0 ]; then
          echo "Artifacts skipped because of deployment-scanner configuration: ${artifactsskipped[*]}"
        fi

        if [ ${#artifactsfailed[@]} -gt 0 ]; then
          echo "Failed deployments: ${artifactsfailed[*]}"
        fi

        if [ ${#artifactsdeployed[@]} -gt 0 ]; then
          echo "Artifacts deployed: ${artifactsdeployed[*]}"
        fi

        if [ ${#artifactsunknown[@]} -gt 0 ]; then
          echo "Artifacts in an unknown state: ${artifactsunknown[*]}"
        fi
      else
          echo "Deployment scanner disabled, skipping deployment verification"
      fi
    fi
}

# Check if the jbossas process is running
function isrunning() {

    # Check for running app
    if [ -f "$JBOSSEAP_PID_FILE" ]; then
      jbpid=$(cat $JBOSSEAP_PID_FILE);
      if /bin/ps --pid $jbpid 1>&2 >/dev/null;
      then
        return 0
      fi
    fi

    return 1
}

# Kill the process given by $1 and its children
killtree() {
    local _pid=$1
    for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
        killtree ${_child}
    done

    local should_be_gone_pid=$(ps -o pid -p ${_pid} --no-headers)
    if [ -z "$should_be_gone_pid" ]; then
        return
    else
        kill -TERM ${_pid}
    fi

    local count=0
    while [ ${count} -lt 15 ]
    do
        local should_be_gone_pid=$(ps -o pid -p ${_pid} --no-headers)
        if [ -z "$should_be_gone_pid" ]; then
                return
        else
                sleep 2
                let count=${count}+1
        fi
    done

    local should_be_gone_pid=$(ps -o pid -p ${_pid} --no-headers)
    if [ ! -z $should_be_gone_pid ]
    then
        kill -9 ${_pid}
    fi
}

# Check if the server http port is up
function ishttpup() {

    let count=0
    while [ ${count} -lt 64 ]
    do
        if /usr/sbin/lsof -P -n -i "@${OPENSHIFT_JBOSSEAP_IP}:${OPENSHIFT_JBOSSEAP_HTTP_PORT}" | grep "(LISTEN)" > /dev/null; then
            echo "Found ${OPENSHIFT_JBOSSEAP_IP}:${OPENSHIFT_JBOSSEAP_HTTP_PORT} listening port"
            return 0
        fi
        let count=${count}+1

        sleep 2
    done

    return 1
}

# Check if the server mgmt port is up
function ismgmtup() {
    let count=0
    while [ ${count} -lt 10 ]
    do
        if /usr/sbin/lsof -P -n -i "@${OPENSHIFT_JBOSSEAP_IP}:${OPENSHIFT_JBOSSEAP_MANAGEMENT_NATIVE_PORT}" | grep "(LISTEN)" > /dev/null; then
            echo "Found ${OPENSHIFT_JBOSSEAP_IP}:${OPENSHIFT_JBOSSEAP_MANAGEMENT_NATIVE_PORT} listening port"
            return 0
        fi
        let count=${count}+1

        sleep 2
    done

    return 1
}

function build() {
  echo "Building $cartridge_type cartridge"

  CONFIG_DIR="${OPENSHIFT_JBOSSEAP_DIR}/standalone/configuration"
  OPENSHIFT_MAVEN_MIRROR="${CONFIG_DIR}/settings.base.xml"
  if $(echo $OPENSHIFT_GEAR_DNS | egrep -qe "\.rhcloud\.com")
  then
      OPENSHIFT_MAVEN_MIRROR="${CONFIG_DIR}/settings.rhcloud.xml"
  fi

  max_memory_mb=${OPENSHIFT_GEAR_MEMORY_MB}

  # If hot deploy is enabled, we need to restrict the Maven memory size to fit
  # alongside the running application server. For now, just hard-code it to 64
  # and figure out how to apply a scaling factor later.
  if hot_deploy_enabled_for_latest_deployment
  then
      echo "Scaling down Maven heap settings due to presence of hot_deploy marker"

      if [ -z "$MAVEN_JVM_HEAP_RATIO" ]; then
      MAVEN_JVM_HEAP_RATIO=0.25
    fi
  else
    if [ -z "$MAVEN_JVM_HEAP_RATIO" ]; then
      MAVEN_JVM_HEAP_RATIO=0.75
    fi
  fi

  max_heap=$( echo "$max_memory_mb * $MAVEN_JVM_HEAP_RATIO" | bc | awk '{print int($1+0.5)}')

  OPENSHIFT_MAVEN_XMX="-Xmx${max_heap}m"

  if [ -z "$BUILD_NUMBER" ]
  then
      if force_clean_build_enabled_for_latest_deployment
      then
          echo "Force-clean build is enabled. Removing Maven dependencies." 1>&2
          rm -rf ${OPENSHIFT_HOMEDIR}.m2/* ${OPENSHIFT_HOMEDIR}.m2/.[^.]*
      fi

      if [ -f ${OPENSHIFT_REPO_DIR}pom.xml ] && ! marker_present skip_maven_build
      then
          update-configuration

          export MAVEN_OPTS="$OPENSHIFT_MAVEN_XMX"
          pushd ${OPENSHIFT_REPO_DIR} > /dev/null

          if [ -z "$MAVEN_OPTS" ]; then
            export MAVEN_OPTS="$OPENSHIFT_MAVEN_XMX"
          fi

          if [ -z "$MAVEN_ARGS" ]; then
          export MAVEN_ARGS="clean package -Popenshift -DskipTests"
          fi

          echo "Found pom.xml... attempting to build with 'mvn -e ${MAVEN_ARGS}'"

          if [ -n "$OPENSHIFT_MAVEN_MIRROR" ]
          then
              mvn --global-settings $OPENSHIFT_MAVEN_MIRROR --version
              mvn --global-settings $OPENSHIFT_MAVEN_MIRROR $MAVEN_ARGS
          else
              mvn --version
              mvn $MAVEN_ARGS
          fi
          popd > /dev/null

          CART_NAME=${cartridge_type}
      fi
  fi

}

function deploy() {
  echo "Deploying $cartridge_type cartridge"

  # if repo/deployments has any files in it, sync them to $JBOSSEAP_DEPLOYMENTS_DIR
  # and delete any files in $JBOSSEAP_DEPLOYMENTS_DIR that don't exist in
  # repo/deployments
  if [ "$(ls ${OPENSHIFT_REPO_DIR}/deployments 2>/dev/null)" ]; then
    rsync -r --delete --exclude ".*" ${OPENSHIFT_REPO_DIR}/deployments/ $JBOSSEAP_DEPLOYMENTS_DIR
  fi
}

function start() {
  if marker_present "enable_jpda"; then
    export ENABLE_JPDA=1
  fi

  # Check for running app
  if isrunning; then
    echo "Application is already running"
  else
    echo "Starting $cartridge_type cartridge"

    ${JBOSSEAP_BIN_DIR}/standalone.sh > ${OPENSHIFT_TMP_DIR}/${cartridge_type}.log 2>&1 &
    PROCESS_ID=$!
    echo "$PROCESS_ID" > ${JBOSSEAP_PID_FILE}

    if ! ishttpup; then
      echo "Timed out waiting for http listening port"
      exit 1
    fi

    waitondeployments
  fi
}


function stop() {
    if [ -f "$JBOSSEAP_PID_FILE" ]; then
      echo "Stopping $cartridge_type cartridge"
      pid=$(cat $JBOSSEAP_PID_FILE);
      echo "Sending SIGTERM to jboss:$pid ..." 1>&2
      killtree $pid
    else 
      echo "Failed to locate JBOSS PID File" 1>&2
    fi
}

function restart() {
    stop
    start
}

function status() {
   if isrunning
   then
      client_result "Application is running"
   else
      client_result "Application is either stopped or inaccessible"
   fi
}

function reload() {
    restart
}

# Clean up any log files
function tidy() {
  client_message "Emptying log dir: $OPENSHIFT_JBOSSEAP_LOG_DIR"
  shopt -s dotglob
  rm -rf $OPENSHIFT_JBOSSEAP_LOG_DIR/*
}

function threaddump() {
  echo "Thread dump for $cartridge_type cartridge"

    if ! isrunning; then
        echo "Application is stopped"
        exit 1
    elif [ -f "$JBOSSEAP_PID_FILE" ]; then
        pid=$(cat $JBOSSEAP_PID_FILE);
        java_pid=$(ps h --ppid $pid -o '%p')
        kill -3 $java_pid

        client_result "Success"
        client_result ""
        client_result "The thread dump file will be available via: rhc tail $OPENSHIFT_APP_NAME -f ${OPENSHIFT_TMP_DIR}${cartridge_type}.log -o '-n 250'"
    else 
        echo "Failed to locate JBOSS PID File"
    fi
}

export OPENSHIFT_SECRET_TOKEN=${OPENSHIFT_SECRET_TOKEN:-OPENSHIFT_APP_UUID}

case "$1" in
  build)           build ;;
  deploy)          deploy ;;
  start)           start ;;
  stop)            stop ;;
  restart)         restart ;;
  status)          status ;;
  reload)          reload ;;
  tidy)            tidy ;;
  threaddump)      threaddump ;;
  update-configuration) update-configuration ;;
  *)               exit 0
esac

