#!/bin/bash

#== 脚本执行中遇到不存在的变量就报错
set -o nounset
#== 脚本执行中报错即刻退出
set -o errexit
#== 脚本执行只要一个子命令失败，整个管道命令就失败
set -o pipefail

readonly BRAND_FORMAL_NAME="Cloudwise"
readonly BRAND_PRODUCT_NAME="euspace"
readonly BRAND_PARENT_PRODUCT_NAME="omniagent"
readonly BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME}"
readonly BRAND_FORMAL_NAME_LOWER="cloudwise"
readonly BRAND_PRODUCT_NAME_LOWER="euspace"
#== **********************************************************
#==  配置目录
#== **********************************************************
readonly INSTALL_BASE=/opt
#== /opt/cloudwise/omniagent/agents 目录
readonly BASE_INSTALL_DIR=${INSTALL_BASE}/${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents
#== cloudwise/omniagent/agents/agent
readonly INSTALL_FOLDER=${BRAND_FORMAL_NAME_LOWER}/${BRAND_PARENT_PRODUCT_NAME}/agents/${BRAND_PRODUCT_NAME_LOWER}
#== cloudwise/omniagent/agents/agent/version
readonly INSTALL_VERSION_FOLDER=${INSTALL_FOLDER}/current
#== /opt/cloudwise/omniagent/agents/agent/version
readonly INSTALL_DIR=${INSTALL_BASE}/${INSTALL_VERSION_FOLDER}
#== /opt/cloudwise/omniagent/agents/agent
readonly AGENT_BASE_DIR=${INSTALL_BASE}/${INSTALL_FOLDER}

readonly AGENT_BIN_DIR="${INSTALL_DIR}/bin"
readonly AGENT_LOG_DIR="${INSTALL_DIR}/logs"

#readonly AGENT_CONF_DIR="${INSTALL_DIR}/conf"
#readonly MAIN_CONF_FILE="${AGENT_CONF_DIR}/${AGENT_MAIN_CONF}"
readonly EXIT_CODE_OK=0
readonly EXIT_CODE_GENERIC_ERROR=1

#== **********************************************************
#==  配置重要文件名称
#== **********************************************************
readonly AGENT_PROC="euspace"
readonly AGENT_CONFIG_PATH="${INSTALL_DIR}/conf/config.yaml"

readonly AGENT_PID_FILE="${INSTALL_DIR}/bin/${AGENT_PROC}.pid"


getDaemonPid(){
    local agent="${1}"
    #== 约定pid文件
    local pidFilePath="${AGENT_PID_FILE}"
    #== 二进制文件绝对路径
    # shellcheck disable=SC2155
    local procPath="$(readlink -m "${AGENT_BIN_DIR}/${agent}" 2>&1)"
    local cmdline
    local pid
    #== 查询pid文件
    if [ -s "${pidFilePath}" ] ; then
      pid="$(cat "${pidFilePath}" 2>&1)"
      cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
      if [ -d "/proc/${pid}" ] && ( [[ ${cmdline} =~ ${procPath} ]] || [[ ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]] ); then
#        toLogInfo "[${agent}] Find pid by ${pidFilePath} [content:${pid}][cmdline:${cmdline}]"
          printf '%s' ${pid}
          return 0
      else
        #== 进程绝对路径查询
#        toLogWarning "[${agent}] Pidfile exist [content:${pid}]. But process not find or not myself. [cmdline:${cmdline}]"
        if ! pid="$(listProcesses "${agent} pid" "${procPath}|${AGENT_BIN_DIR}/${agent}" "sudo|tail")"; then
#          toLogWarning "[${agent}] Not find process grep '${procPath}'"
          return 1
        fi
        cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
        if ! [[ ${cmdline} =~ ${procPath} || ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]]; then
#            toLogWarning "[${agent}] Find process success. But process not myself. [cmdline:${cmdline}]"
            return 1
        fi
#        toLogInfo "[${agent}] Find pid by process name [${procPath}|${AGENT_BIN_DIR}/${agent}]"
      fi
    else
      #== 进程绝对路径查询
#      toLogWarning "[${agent}] Pidfile [${pidFilePath}] not find. Use abs path queries."
      if ! pid="$(listProcesses "${agent} pid" "${procPath}|${AGENT_BIN_DIR}/${agent}" "sudo|tail")"; then
#        toLogWarning "[${agent}] Not find process by grep '${procPath}'"
        return 1
      fi
      cmdline="$(cat /proc/${pid}/cmdline 2>&1 | xargs -0 echo -n)"
      if ! [[ ${cmdline} =~ ${procPath} || ${cmdline} =~ ${AGENT_BIN_DIR}/${agent} ]]; then
#          toLogWarning "[${agent}] Find process success. But process not myself. [cmdline:${cmdline}]"
          return 1
      fi
#      toLogInfo "[${agent}] Find pid by process name [${procPath}|${AGENT_BIN_DIR}/${agent}]."
    fi

    printf '%s' ${pid}
    return 0
}

listProcesses() {
  local errorMessage="${1}"
  local includeRegex="${2}"

  local excludeRegex=" grep"
  if [ "${3}" ]; then
    excludeRegex="grep|${3}"
  fi

#  toLogInfo "#DEBUG== listProcesses command: ps -e -o \"pid,args\" 2>&1 | grep -E "${includeRegex}" | awk '{{ print \$1,\$2 }}' | grep -vE \"${excludeRegex}\""
  local output
  if ! output="$(ps -e -o "pid,args" 2>&1 | grep -E "${includeRegex}" | awk '{{ print $1,$2 }}')"; then
#    toLogError "Failed to get ${errorMessage}, output: ${output}"
    return 1
  fi

  local foundProcesses="$(printf '%s' "${output}" | grep -vE "${excludeRegex}")"
  if [ ! "${foundProcesses}" ]; then
    return 1
  fi

  printf '%s' "${foundProcesses}" | awk '{{ print $1 }}'
  return 0
}

getAgentPid() {
  local DAEMONPID="$(getDaemonPid "${AGENT_PROC}")"
  if [ -z ${DAEMONPID} ]; then
      return 1
  fi
  printf '%s' "${DAEMONPID}"

}

startAgent() {
  local pid
  if [ -f "${AGENT_BIN_DIR}/${AGENT_PROC}" ]; then
    export DISABLE_E2E_TRACING=false
    export DISABLE_STACK_TRACING=true
    export RUN_IN_OMNIAGENT=true
#    export LOG_LEVEL=debug
#    export SEND_NET_DATA=true
#    export ENABLE_ES=true
    export SEND=1
    local params="--listen=0.0.0.0:8123"
#    if [ -f "/etc/chaosd/pki/ca.crt" ] && [ -f "/etc/chaosd/pki/chaosd.crt" ] && [ -f "/etc/chaosd/pki/chaosd.key" ]; then
#        params="server  --https-port 31768 --CA=/etc/chaosd/pki/ca.crt --cert=/etc/chaosd/pki/chaosd.crt --key=/etc/chaosd/pki/chaosd.key"
#    fi
    pid=$(nohup ${AGENT_BIN_DIR}/${AGENT_PROC} ${params}>>"${AGENT_LOG_DIR}/service.log" 2>&1 & echo $!)
    echo ${pid} > "${AGENT_PID_FILE}"
  else
    echo "${AGENT_BIN_DIR}/${AGENT_PROC} not exist."
    exit "${EXIT_CODE_GENERIC_ERROR}"
  fi

}

agentStart() {
  local agentPid
  if agentPid="$(getAgentPid)"; then
    echo "${BRAND_AGENT_PRODUCT_NAME} is running. Agent pid: ${agentPid}."
    return
  fi

  startAgent
	local exitCode=$?
	if [ "${exitCode}" -ne 0 ]; then
		echo "Failed to start ${BRAND_AGENT_PRODUCT_NAME} service."
		exit "${EXIT_CODE_GENERIC_ERROR}"
	fi

  if agentPid="$(getAgentPid)"; then
    echo "${BRAND_AGENT_PRODUCT_NAME} service started. Agent pid: ${agentPid}."
  else
    echo "${BRAND_AGENT_PRODUCT_NAME} not start!"
    exit "${EXIT_CODE_GENERIC_ERROR}"
  fi
}

agentStop() {
  local agentPid
  if agentPid="$(getAgentPid)"; then
#    ${AGENT_BIN_DIR}/stop.sh ${agentPid}
    kill ${agentPid}
    echo "${BRAND_AGENT_PRODUCT_NAME} service stopped success."
    cat /dev/null > "${AGENT_PID_FILE}"
  else
      echo "${BRAND_AGENT_PRODUCT_NAME} is stopped. service stopped success."
  fi
}

agentRestart(){
  agentStop
  sleep 1
  agentStart
}

agentStatus() {
  local agentPid
	local statusOutput
  if agentPid="$(getAgentPid)"; then
    statusOutput="${BRAND_AGENT_PRODUCT_NAME} is running. ${BRAND_AGENT_PRODUCT_NAME} pid: ${agentPid}"
  else
    statusOutput="${BRAND_AGENT_PRODUCT_NAME} is not running. ${BRAND_AGENT_PRODUCT_NAME} process not found or stop."
  fi

  echo "${statusOutput}"
}

info() {
  local agentPid="$(getAgentPid)"
  local version=$(cat "${INSTALL_DIR}/installer.version" | tr -d '\n')
  printf '{"pid":%d,"version":"%s","agent_id":"%s","config":"%s","pipe": true}' "${agentPid}" "${version}" "${BRAND_PRODUCT_NAME_LOWER}" "${AGENT_CONFIG_PATH}"
}

################################################################################
#
# Script start
#
################################################################################

main() {
  case "$1" in
  start)
    agentStart
    ;;
  stop)
    agentStop
    ;;
  restart)
    agentRestart
    ;;
  status)
    agentStatus
    ;;
  info)
    info
    ;;
  *)
    toConsoleInfo "usage: $0 {start|stop|restart|status}"
    ;;
  esac

  exit "${EXIT_CODE_OK}"
}

main "$@"
