#!/bin/bash

AGENT_INSTALLER_VERSION=1.0.0

#== 当前脚本必须放在 smartagent/scripts 目录下
readonly SCRIPT_PATH=$(dirname $0)
readonly SCRIPT_DIR=$(cd $SCRIPT_PATH && pwd)
readonly CURR_FILE_NAME="$(basename "$0")"
readonly SMARTAGENT_DIR=$(cd $SCRIPT_DIR/../ && pwd)
readonly SMARTAGENT_PARENT_DIR=$(cd $SCRIPT_DIR/../../ && pwd)

readonly BRAND_FORMAL_NAME="Cloudwise"
BRAND_PRODUCT_NAME="euspace"
BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}"
readonly BRAND_FORMAL_NAME_LOWER="cloudwise"
readonly BRAND_PRODUCT_NAME_LOWER="cwserveragent"
readonly BRAND_AGENT_DEFAULT_USER_AND_GROUP_NAME="ucloudwise"


readonly BAK_EXT_NAME=".bak"
#== cw-serveragent
readonly SERVICE_SCRIPT_FILE="cw-oneagent"
readonly XZDEC_NAME="xzdec"
readonly INSTALL_TEMP_FILE_NAME="install_temp.sh"
readonly INSTALL_VERSION_FILE_NAME="installer.version"
#== {productName}-installer-{version}.sh 即 cwserveragent-installer-1.1.0.sh
ARCH=$(uname -m)
TARGET_INSTALL_FILE_NAME="${BRAND_AGENT_PRODUCT_NAME}-installer-Linux-${ARCH}-${AGENT_INSTALLER_VERSION}.sh"
#TARGET_INSTALL_FILE_NAME="${BRAND_PRODUCT_NAME_LOWER}-installer-${AGENT_INSTALLER_VERSION}.sh"

TARGET_INSTALL_TMP_FILE="${SMARTAGENT_PARENT_DIR}/${TARGET_INSTALL_FILE_NAME}.tmp"

readonly LOG_DIR="${SMARTAGENT_PARENT_DIR}/logs"
readonly LOG_FILE_NAME="release.log"
readonly LOG_FILE="${LOG_DIR}/${LOG_FILE_NAME}"

#== 【0】=【退出码】执行成功
readonly EXIT_CODE_OK=0
readonly EXIT_CODE_GENERIC_ERROR=1
readonly EXIT_CODE_NOT_ENOUGH_SPACE=6
readonly EXIT_CODE_NOT_ENOUGH_MEMORY=7
#== 【0】=无效参数
readonly EXIT_CODE_INVALID_PARAM=8
readonly EXIT_CODE_INSUFFICIENT_PERMISSIONS=9
readonly EXIT_CODE_SEMANAGE_NOT_FOUND=10
readonly EXIT_CODE_WATCHDOG_ALREADY_RUNNING=11
#== 【退出码】接收信号
readonly EXIT_CODE_SIGNAL_RECEIVED=12
readonly EXIT_CODE_ANOTHER_INSTALLER_RUNNING=13
readonly EXIT_CODE_AGENT_CONTAINER_RUNNING=14
readonly EXIT_CODE_GLIBC_VERSION_TOO_LOW=15
readonly EXIT_CODE_CORRUPTED_PACKAGE=16
#== 【退出码】管理系统环境变量配置
readonly EXIT_CODE_MISCONFIGURED_ENVIRONMENT=17
readonly EXIT_CODE_UNSUPPORTED_DOWNGRADE=18
readonly EXIT_CODE_OS_NOT_SUPPORTED=19
readonly EXIT_CODE_DEL_DEFAULT_PARAMS=20

readonly LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS=50
#**********************************************************
# Logs
#**********************************************************
toLogFile() {
  if [ -e "${LOG_FILE}" ]; then
    printf '%s UTC %s\n' "$(date -u +"%Y-%m-%d %H:%M:%S")" "$*" >>"${LOG_FILE}" 2>/dev/null
  fi
}

toConsoleOnly() {
  printf '%s %s\n' "$(date +"%H:%M:%S")" "$*" 2>/dev/null
}

toLogInfo() {
  toLogFile "[INFO]" "$@"
}

toLogWarn() {
  toLogFile "[WARN]" "$@"
}

toLogError() {
  toLogFile "[ERROR]" "$@"
}

toLogAdaptive() {
  local success="${1}"
  shift
  if [ "${success}" -eq 0 ]; then
    toLogInfo "$@"
  else
    toLogError "$@"
  fi
}

toConsoleInfo() {
  toConsoleOnly "$@"
  toLogInfo "$@"
}

toConsoleWarn() {
  toConsoleOnly "Warn:" "$@"
  toLogWarn "$@"
} >&2

toConsoleError() {
  toConsoleOnly "Error:" "$@"
  toLogError "$@"
} >&2

#**********************************************************
# compress
#**********************************************************
tarSmartAgent() {
  toConsoleInfo "There are 5 steps to packing, begin package ${BRAND_AGENT_PRODUCT_NAME}...."
  #== 将打包脚本（package.sh、xzdec、install_temp.sh、smartagent、uninstall.sh）移动到临时目录
  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
    mv -f "${SCRIPT_DIR}/${fileNm}" "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" 2>>"${LOG_FILE}"
  done
  mv -f "${SCRIPT_DIR}/${XZDEC_NAME}" "${SMARTAGENT_PARENT_DIR}/" 2>>"${LOG_FILE}"
  cp -f "${SMARTAGENT_PARENT_DIR}/${INSTALL_TEMP_FILE_NAME}${BAK_EXT_NAME}" "${TARGET_INSTALL_TMP_FILE}" 2>>"${LOG_FILE}"

  for fileNm in "uninstall.sh"; do
    cp -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" "${SCRIPT_DIR}/${fileNm}" 2>>"${LOG_FILE}"
  done

  #== 删除安装脚本中注释
  if [ "${PARAM_DEBUG}"x != "true"x ]; then
    toConsoleInfo "Delete the type [#==] comment ..."
    sed -i '/#==/d' "${TARGET_INSTALL_TMP_FILE}"
#    sed -i '/#==/d' "${SCRIPT_DIR}/${SERVICE_SCRIPT_FILE}"
    sed -i '/#==/d' "${SCRIPT_DIR}/uninstall.sh"
    toConsoleInfo "Delete the type [#DEBUG==] comment ..."
    sed -i '/#DEBUG==/d' "${TARGET_INSTALL_TMP_FILE}"
#    sed -i '/#DEBUG==/d' "${SCRIPT_DIR}/${SERVICE_SCRIPT_FILE}"
    sed -i '/#DEBUG==/d' "${SCRIPT_DIR}/uninstall.sh"
  fi

  if [ "${PARAM_RELEASE}"x = "true"x ]; then
    deleteDefaultParams "${TARGET_INSTALL_TMP_FILE}"
  fi

  #== 进入 smartagent 目录下
  cd "${SMARTAGENT_DIR}"
  cp -f "${SCRIPT_DIR}/uninstall.sh" ./package_dir
  #== 执行第一阶段压缩（源码压缩）Cloudwise-SmartAgent.tar
  toConsoleInfo "step【1】start【tar -cpf "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar" ./package_dir/*】to ${BRAND_AGENT_PRODUCT_NAME}.tar"
  tar -cpf "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar" --exclude="*.gitkeep" --exclude="*.log" ./package_dir/* >>"${LOG_FILE}" 2>&1
  rm -f "./package_dir/uninstall.sh"

  if [ $? -ne 0 ]; then
    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
  fi
  local agentTarSize="$(getStorageSize "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar")"

  cd "${SMARTAGENT_PARENT_DIR}"
  #== 执行第二阶段压缩（源码压缩 Cloudwise-SmartAgent.tar.xz
  toConsoleInfo "step【2】start【xz -T0 -z ${BRAND_AGENT_PRODUCT_NAME}.tar】to ${BRAND_AGENT_PRODUCT_NAME}.tar.zx"
  xz -T0 -1 -z "${BRAND_AGENT_PRODUCT_NAME}.tar" -vv
  if [ $? -ne 0 ]; then
    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
  fi

  #== 执行第三阶段压缩 Cloudwise-SmartAgent.tar.xz xzdec to Cloudwise-SmartAgent.tar
  toConsoleInfo "step【3】start【tar -cpf ${BRAND_AGENT_PRODUCT_NAME}.tar ${BRAND_AGENT_PRODUCT_NAME}.tar.xz xzdec】 to ${BRAND_AGENT_PRODUCT_NAME}.tar"
  tar -cpf "${BRAND_AGENT_PRODUCT_NAME}.tar" "${BRAND_AGENT_PRODUCT_NAME}.tar.xz" xzdec >>"${LOG_FILE}" 2>&1
  if [ $? -ne 0 ]; then
    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
  fi

  #== 执行第四阶段压缩 Cloudwise-SmartAgent.tar to Cloudwise-SmartAgent.tar.base64
  toConsoleInfo "step【4】start【base64 ${BRAND_AGENT_PRODUCT_NAME}.tar > ${BRAND_AGENT_PRODUCT_NAME}.tar.base64】 to ${BRAND_AGENT_PRODUCT_NAME}.tar.base64"
  base64 "${BRAND_AGENT_PRODUCT_NAME}.tar" >"${BRAND_AGENT_PRODUCT_NAME}.tar.base64" 2>>"${LOG_FILE}"
  if [ $? -ne 0 ]; then
    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
  fi

  #== 执行第五阶段将 base64 文件写入安装脚本
  toConsoleInfo "step【5】start write 【${BRAND_AGENT_PRODUCT_NAME}.tar.base64】 to ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}"
  #== 设置脚本中版本、创建时间、占用空间信息
  editInstallScriptParam "${TARGET_INSTALL_TMP_FILE}" ${agentTarSize}

  sed -i "/#################ENDOFSCRIPTMARK################/r ${BRAND_AGENT_PRODUCT_NAME}.tar.base64" "${TARGET_INSTALL_TMP_FILE}"
  if [ $? -ne 0 ]; then
    finishPackage "${EXIT_CODE_GENERIC_ERROR}"
  fi

  toConsoleInfo "${BRAND_AGENT_PRODUCT_NAME} packaging success."
  finishPackage "${EXIT_CODE_OK}"
}

buildVersion() {
  local oldVersion
  if oldVersion="$(getOldVersion)"; then
    setInstallVersion "${oldVersion}"
    removeIfExist "${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}"
		toConsoleInfo "Delete file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}."
  fi

  if [ "${PARAM_VERSION}" ]; then
    setInstallVersion "${PARAM_VERSION}"
    return
  fi
}

setInstallVersion() {
  local version="${1}"
  if [ ! "${version}" ]; then
    toConsoleWarn "Set install version failed，not found version version."
    return
  fi

  AGENT_INSTALLER_VERSION="${version}"
  BRAND_PRODUCT_NAME="${PARAM_NAME}"
  BRAND_AGENT_PRODUCT_NAME="${BRAND_FORMAL_NAME}-${BRAND_PRODUCT_NAME}"
  TARGET_INSTALL_FILE_NAME="${BRAND_AGENT_PRODUCT_NAME}-installer-Linux-${ARCH}-${AGENT_INSTALLER_VERSION}.sh"
  #== {productName}-installer-{version}.sh 即 cwserveragent-installer-1.1.0.sh
#  TARGET_INSTALL_FILE_NAME="${BRAND_PRODUCT_NAME_LOWER}-installer-${AGENT_INSTALLER_VERSION}.sh"
  TARGET_INSTALL_TMP_FILE="${SMARTAGENT_PARENT_DIR}/${TARGET_INSTALL_FILE_NAME}.tmp"
}

getOldVersion() {
	local installVersionFile="${SMARTAGENT_DIR}/installer.version"
	if [ ! -f "${installVersionFile}" ]; then
		toLogWarn "Could not find ${installVersionFile} file."
		return 1
	fi

	local oldVersion="$(cat "${installVersionFile}")"
	if [ ! "${oldVersion}" ]; then
		toLogWarn "Could not read install version from ${installVersionFile} file."
	  return 1
  fi

  printf '%s' "${oldVersion}"
  return 0
}

#== 通过占位分割读取位置
locateDelimiter() {
  #== 占位符
  local delimiter="${1}"
  #== 从文件结尾读取行数
  local linesToReadFromEnd="${2}"
  local filePath="${3}"

  if [ "${linesToReadFromEnd}" ]; then
    #== 文件总行数n（实际行数=n+1）
    local linesCount="$(wc -l "${filePath}" | awk '{print $1}')"
    #== 从后往前读取【linesToReadFromEnd】行
    local offset="$(tail -n"${linesToReadFromEnd}" "${filePath}" 2>/dev/null | awk '/^'"${delimiter}"'/ { print NR; exit }')"
    if [ -n "${offset}" ]; then
      printf "%d" "$((linesCount - linesToReadFromEnd + offset))"
    fi
  else
    #== 读取占位符所在行（实际行数=n+1）
    awk '/^'"${delimiter}"'/ { print NR; exit }' "${filePath}"
  fi
}

#== 删除安装脚本中默认参数
deleteDefaultParams() {
  local filePath="${1}"
  local sectionName="----PARAMETERS"
  local begin=$(locateDelimiter "${sectionName}" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS} ${filePath})
  local end=$(locateDelimiter "${sectionName}--" ${LINES_TO_SEARCH_FOR_SIGNATURE_AND_PARAMS} ${filePath})

  if [ -z "${begin}" ] || [ -z "${end}" ]; then
    return
  fi

  toConsoleInfo "Begin delete default params from line ${begin} to ${end}..."
  local output="$(sed -i "${begin},${end}d" "${filePath}") 2>&1"
  if [ ! "${output}" ]; then
    toConsoleError "Delete install script file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME} default params error：${output}"
    finishPackage "${EXIT_CODE_DEL_DEFAULT_PARAMS}"
  fi
  toConsoleInfo "Delete install script file ${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME} default params success."
}

#== 设置脚本中版本、创建时间、占用空间信息
editInstallScriptParam() {
  local targetFile="${1}"
  local agentTarSize="${2}"
  #== 设置版本信息
  local buildDate="$(date +"%Y-%m-%d")"
  local buildTag="$(git rev-parse --short HEAD)"
  local buildDateInfo="$(date +"%Y-%m-%d %H:%M:%S")"
  local buildUploader="$(hostname)/${USER}"
  #== 构建日期
  editScriptFileParam "readonly AGENT_BUILD_DATE" "${buildDate}" "${targetFile}"
  #== 构建版本
  editScriptFileParam "readonly AGENT_INSTALLER_VERSION" "${AGENT_INSTALLER_VERSION}" "${targetFile}"
  #== commitid
  editScriptFileParam "readonly AGENT_BUILD_TAG" "'${buildTag}'" "${targetFile}"
  #== 构建日期
  editScriptFileParam "readonly AGENT_BUILD_DATE_INFO" "'${buildDateInfo}'" "${targetFile}"
  #== 构建环境信息
  editScriptFileParam "readonly AGENT_BUILD_UPLOADER" "'${buildUploader}'" "${targetFile}"

  #== 设置占用空间信息
  local agentDirSize="$(getStorageSize "${SMARTAGENT_DIR}")"
  local agentBase64FileSize="$(getStorageSize "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.tar.base64")"
  local agentInstallFileSize="$(getStorageSize "${TARGET_INSTALL_TMP_FILE}")"
  local artifactsSize="$((agentBase64FileSize + agentInstallFileSize + agentDirSize))";
  editScriptFileParam "readonly EXTERNAL_TAR_SIZE" "${agentTarSize}" "${targetFile}"
  editScriptFileParam "readonly ARTIFACTS_SIZE" "${artifactsSize}" "${targetFile}"
}

getStorageSize() {
  local dirName="${1}"
  if [ ! -e "${dirName}" ]; then
    printf '%s' "0"
    return 0
  fi
  printf '%s' "$(du -sb "${dirName}" | awk '{print $1}')"
}

finishFinally() {
  #== 将打包脚本文件移动到当前目录下
  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
    if [ -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" ]; then
      mv -f "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}" "${SCRIPT_DIR}/${fileNm}" 2>>"${LOG_FILE}"
    fi
  done
  removeIfExist "${SMARTAGENT_DIR}/uninstall.sh"
  if [ -f "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}" ]; then
    mv -f "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}" "${SCRIPT_DIR}/" 2>>"${LOG_FILE}"
  fi

  if [ -f "${TARGET_INSTALL_TMP_FILE}" ]; then
    mv -f "${TARGET_INSTALL_TMP_FILE}" "${SMARTAGENT_DIR}/${TARGET_INSTALL_FILE_NAME}" 2>>"${LOG_FILE}"
  fi

  if [ "${PARAM_DEBUG}"x != "true"x ]; then
    for fileNmExt in "tar" "tar.xz" "tar.base64"; do
      removeIfExist "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.${fileNmExt}"
    done
  fi


}

removeIfExist() {
  local filePath="${1}"
  if [ ! -e "${filePath}" ]; then
    return
  fi
  rm -rf "${filePath}" 2>>"${LOG_FILE}"
}

deleteParentTmpFile() {
  for fileNm in "${CURR_FILE_NAME}" "${INSTALL_TEMP_FILE_NAME}" "uninstall.sh"; do
    removeIfExist "${SMARTAGENT_PARENT_DIR}/${fileNm}${BAK_EXT_NAME}"
  done
  removeIfExist "${SMARTAGENT_PARENT_DIR}/${XZDEC_NAME}"
  removeIfExist "${TARGET_INSTALL_TMP_FILE}"

  for fileNmExt in "tar" "tar.xz" "tar.base64"; do
    removeIfExist "${SMARTAGENT_PARENT_DIR}/${BRAND_AGENT_PRODUCT_NAME}.${fileNmExt}"
  done
}

#**********************************************************
# Param
#**********************************************************
PARAM_DEBUG=false
PARAM_RELEASE=false
#PARAM_VERSION=1.1.0
PARAM_NAME=euspace
PARAM_AGENT_PROC=$PARAM_NAME
PARAM_CONFIG_PATH=

#== 大小写转化，并返回判断结果
istrcmp() {
  local s1="$(printf '%s' "${1}" | tr '[:upper:]' '[:lower:]')"
  local s2="$(printf '%s' "${2}" | tr '[:upper:]' '[:lower:]')"
  [ "${s1}"x = "${s2}"x ]
}

isParamTrue() {
  [ "${1}"x = "1"x ] || [ "${1}"x = "true"x ] || [ "${1}"x = "enable"x ] || [ "${1}"x = "yes"x ]
}

isParamFalse() {
  [ "${1}"x = "0"x ] || [ "${1}"x = "false"x ] || [ "${1}"x = "disable"x ] || [ "${1}"x = "no"x ]
}

#== 获取参数值
getParamValue() {
  local paramName="${1}"
  local input="${2}"
  local paramNameLength="${#paramName}"
  paramNameLength=$((paramNameLength + 1))

  local partParam="$(expr substr "${input}" 1 ${paramNameLength})"
  if ! istrcmp "${partParam}" "${paramName}="; then
    return 1
  fi

  local valueSeparator=$((paramNameLength + 1))
  local value="$(expr substr "${input}" ${valueSeparator} 1000)"
  if [ -z "${value}" ]; then
    return 1
  fi

  printf '%s' "${value}"
  return 0
}

#== 获取bool参数
readBoolParam() {
  local value=
  if value="$(getParamValue "${1}" "${2}")"; then
    if isParamFalse "${value}"; then
      printf "false"
      return 0
    fi
    if isParamTrue "${value}"; then
      printf "true"
      return 0
    fi
  fi

  return 1
}

#== 解析命令行中参数
parseCommandLineParameters() {
  while [ $# -gt 0 ]; do
    local param="${1}"
    local value=

    if value=$(getParamValue RELEASE "${param}"); then
      PARAM_RELEASE="${value}"
      printParamMessage "RELEASE" "${value}"
      shift
      continue
    fi

    if value=$(getParamValue VERSION "${param}"); then
      PARAM_VERSION="${value}"
      printParamMessage "VERSION" "${value}"
      shift
      continue
    fi

    if value=$(getParamValue NAME "${param}"); then
      PARAM_NAME="${value}"
      printParamMessage "NAME" "${value}"
      shift
      continue
    fi

    if value=$(getParamValue CONFIG "${param}"); then
      PARAM_CONFIG_PATH="${value}"
      printParamMessage "CONFIG" "${value}"
      shift
      continue
    fi

    if value=$(getParamValue PROC "${param}"); then
      PARAM_AGENT_PROC="${value}"
      printParamMessage "PROC" "${value}"
      shift
      continue
    fi

    if value=$(readBoolParam DEBUG "${param}"); then
      PARAM_DEBUG="${value}"
      printParamMessage "DEBUG" "${value}"
      shift
      continue
    fi

    if [ "${param}"x = "-h"x ] || [ "${param}"x = "--help"x ]; then
      displayHelp
      finishPackage "${EXIT_CODE_OK}"
    fi

    if [ "${param}"x = "-v"x ] || [ "${param}"x = "--version"x ]; then
      printf "%s\n" "${AGENT_INSTALLER_VERSION}"
      finishPackage "${EXIT_CODE_OK}"
    fi

    toConsoleError "Unrecognized parameter: ${param}"

    displayHelp
    finishPackage "${EXIT_CODE_INVALID_PARAM}"
  done
}

displayHelp() {
  printf '\n'
  printf '%s\n' "Usage: "${CURR_FILE_NAME}" [-h] [-v] [NAME=pluginName] [PROC=mainProcess] [RELEASE=true|false] [DEBUG=true|false] [VERSION=1.0]"
  printf '\n\n'

  local pad=15
  printf "%-${pad}s%s\n" "-h, --help" "Display this help and exit."
  printf "%-${pad}s%s\n" "-v, --version" "Print version and exit."
  printf '\n'
  printf "%-${pad}s%s\n" "RELEASE" "Default true; Whether to delete the publish parameter in the script."
  printf "%-${pad}s%s\n" "VERSION" "Configure the ${BRAND_FORMAL_NAME} ${BRAND_PRODUCT_NAME} version."
  printf "%-${pad}s%s\n" "NAME" "Setting agent name like 'bash ./scripts/package.sh NAME=pluginName PROC=mainProcess'"
  printf "%-${pad}s%s\n" "PROC" "Setting agent main process name."
  printf "%-${pad}s%s\n" "DEBUG" "Default false; 1、Debug mode executed script ${CURR_FILE_NAME}；"
  printf "%-${pad}s%s\n" "" "2、Remove the debug log from the scripts (${TARGET_INSTALL_FILE_NAME}、${SERVICE_SCRIPT_FILE}、uninstall.sh)."
}

#== 完成安装后清理临时目录
finishPackage() {
  finishFinally
  toLogInfo "Installation finished, PID $$, exit code: ${1}."
  exit "${1}"
}

printParamMessage() {
  local paramNm="${1}"
  local paramValue="${2}"
  toConsoleInfo "---> Parameter ${paramNm}=${paramValue}."
}

#**********************************************************
# SELinux related functions
#**********************************************************
#== 修改scripts/smartagent脚本配置信息
editScriptFileParam() {
  local key="${1}"
  local newValue="${2}"
  local file="${3}"

  local value="$(sed -n "s|^${key}=||p" "${file}" 2>/dev/null)"
  toConsoleInfo "---> edit ${key}=${value} to ${key}=${newValue}, configFile: ${file}"
  if [ "${value}" ]; then
    sed -i "s|^${key}=.*|${key}=${newValue}|" "${file}" 2>/dev/null
  fi
}

#== 信号捕获，并执行回调函数
signalHandler() {
  local signal="${1}"
  local callback="${2}"
  toLogWarn "process received signal: ${signal}"
  ${callback} "${signal}"
  exit ${EXIT_CODE_SIGNAL_RECEIVED}
}

#== 配置信号捕获和回调
configureSignalHandling() {
  local callback="${1}"
  for signal in HUP INT QUIT ABRT ALRM TERM; do
    #== shellcheck disable=SC2064
    trap "signalHandler ${signal} ${callback}" ${signal}
  done

  trap "" PIPE
}

#**********************************************************
# main
#**********************************************************
main() {
  mkdir -p "${LOG_DIR}"
  echo "" >"${LOG_FILE}"

  toConsoleInfo "package script run path: ${SCRIPT_DIR}"
  toConsoleInfo "package logs path: ${LOG_DIR}"

  chmod +x ${SCRIPT_DIR}/*

  #== 解析命令行参数
  parseCommandLineParameters "$@"
  toConsoleInfo "-----params PARAM_RELEASE: ${PARAM_RELEASE}, PARAM_DEBUG: ${PARAM_DEBUG}, PARAM_VERSION: ${PARAM_VERSION}"

  configureSignalHandling "finishFinally"

  #== 设置 package 插件名
  editScriptFileParam "BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/package.sh"
  #== 设置 install 插件名
  editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/install_temp.sh"
  editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/install_temp.sh"
  #== 设置 agentctl 插件名(存在时)
  if [ -f "${SMARTAGENT_DIR}/package_dir/bin/agentctl" ];then
    editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
    editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
  #== 设置 agentctl 配置文件路径(存在时)
    editScriptFileParam "readonly AGENT_CONFIG_PATH" "\"${PARAM_CONFIG_PATH}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
  fi

  #== 设置 uninstall 插件名
  editScriptFileParam "readonly BRAND_PRODUCT_NAME" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/uninstall.sh"
  editScriptFileParam "readonly BRAND_PRODUCT_NAME_LOWER" "\"${PARAM_NAME}\"" "${SCRIPT_DIR}/uninstall.sh"
  #== 设置主进程名
  if [ -n "${PARAM_AGENT_PROC}" ]; then
    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SCRIPT_DIR}/install_temp.sh"
    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SCRIPT_DIR}/uninstall.sh"
    editScriptFileParam "readonly AGENT_PROC" "\"${PARAM_AGENT_PROC}\"" "${SMARTAGENT_DIR}/package_dir/bin/agentctl"
  fi
  buildVersion
  toConsoleInfo "-----Write release version ${AGENT_INSTALLER_VERSION} to ${SMARTAGENT_DIR}/${INSTALL_VERSION_FILE_NAME} file."
  echo "${AGENT_INSTALLER_VERSION}">"${SMARTAGENT_DIR}/${INSTALL_VERSION_FILE_NAME}"

  #== 修改uninstall.sh 版本
  editScriptFileParam "readonly AGENT_INSTALLER_VERSION" "${AGENT_INSTALLER_VERSION}" "${SCRIPT_DIR}/uninstall.sh"

  deleteParentTmpFile

  #== 压缩 并生成安装脚本
  tarSmartAgent
}

main "$@"
