# Filename:      /usr/share/ngcp-ngcpcfg/functions/main
# Purpose:       helper functions for ngcpcfg
################################################################################
# shellcheck shell=bash

# support for testsuite, assume defaults if unset
FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}"

# do not explain merge commits
export GIT_MERGE_AUTOEDIT=no

if ! [ -r "${FUNCTIONS}"/logs ] ; then
  printf "Error: %s/logs could not be read. Exiting.\n" "${FUNCTIONS}" >&2
  exit 1
fi
# shellcheck disable=SC1090
. "${FUNCTIONS}"/logs

## HA / carrier features {{{
if [ -r "${FUNCTIONS}"/ha_features ] ; then
  # shellcheck disable=SC1090,SC1091
  . "${FUNCTIONS}"/ha_features

  # Set HOST_FILE, NODE_FILE and PAIR_FILE variables, used by ngcpcfg.cfg,
  # tt2-process and encrypt.
  set_ha_vars
fi
## }}}

if ! [ -r "${FUNCTIONS}"/init ] ; then
  log_error "%s/init could not be read. Exiting." "${FUNCTIONS}"
  exit 1
fi
set -o allexport
# shellcheck disable=SC1090
. "${FUNCTIONS}"/init
set +o allexport

## functions {{{
main_action() {
  local rc=0
  ACTION="$1"
  shift

  [ -z "${SUMMARY_ONLY:-}" ] && SUMMARY_ONLY=0

  if [ "${SUMMARY_ONLY}" == "1" ]; then
    log_debug "${SCRIPTS}/${ACTION} $* >(logger -t ngcpcfg --id=\"${NGCPCFG_PID}\") >/dev/null 2>&1"
    "${SCRIPTS}/${ACTION}" "$@" >(logger -t ngcpcfg --id="${NGCPCFG_PID}") >/dev/null 2>&1 || rc=$?
  else
    log_debug "${SCRIPTS}/${ACTION} $*"
    "${SCRIPTS}/${ACTION}" "$@" || rc=$?
  fi

  if [ "${rc}" == "0" ]; then
    local msg="Successfully executed '${ACTION}' on '${HNAME}'"
    [ "${SUMMARY_ONLY}" == "1" ] || log_only "${msg}"
    [ "${SUMMARY_ONLY}" == "0" ] || log_info "${msg}"
  else
    local msg="Failed to call action '${ACTION}' on '${HNAME}' (see logs on '${HNAME}')"
    [ "${SUMMARY_ONLY}" == "1" ] || log_only "Error: ${msg}"
    [ "${SUMMARY_ONLY}" == "0" ] || log_error "${msg}"
    exit "${rc}"
  fi
}

hook_setup() {
  if ${SKIP_UPDATE_PERMS:-false} ; then
    log_debug "skip hook_setup ${1:-}"
    return 0
  fi

  log_debug "hook_setup ${1:-}"

  if ! [ -d "${HOOKS}" ] ; then
    log_debug "Directory ${HOOKS} does not exist."
    return 0
  fi

  local target_directory="$1"

  if [ -z "${1:-}" ] ; then
    log_error "Missing argument for target directory in hook_setup. Exiting."
    exit 1
  fi

  if ! [ -d "${target_directory}" ] ; then
    if [ "${NGCP_TESTSUITE:-false}" = "true" ]; then
      log_info "Hook target directory ${target_directory} not a directory. Creating it."
      mkdir -p "${target_directory}"
    else
      log_error "Hook target directory ${target_directory} not a directory. Exiting."
      exit 1
    fi
  fi

  for hook in "${HOOKS}"/* ; do
    [ -r "${hook}" ] || continue
    log_debug "Creating symlink for ${hook} in ${target_directory}"
    ln -sf "$(readlink -f "${hook}")" "${target_directory}"/
  done
}

compare_active_branch() {
  log_debug "get_active_branch ${1:-}"

  log_debug "cd ${NGCPCTL_MAIN}"
  cd "${NGCPCTL_MAIN}" || return

  local current_branch
  current_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
  log_debug "current_branch = ${current_branch}"
  echo "${current_branch}"
}

get_branch_status() {
  log_debug "cd ${NGCPCTL_MAIN}"
  cd "${NGCPCTL_MAIN}" || return

  log_debug "git rev-parse HEAD"
  local LOCAL
  LOCAL=$(git rev-parse HEAD)

  log_debug "git rev-parse @{u}"
  local REMOTE
  REMOTE=$(git rev-parse '@{u}')

  log_debug "git merge-base HEAD @{u}"
  local BASE
  BASE=$(git merge-base HEAD '@{u}')

  if [ "${LOCAL}" = "${REMOTE}" ]; then
    # Up-to-date
    return 0
  elif [ "${LOCAL}" = "${BASE}" ]; then
    # Need to pull
    return 1
  elif [ "${REMOTE}" = "${BASE}" ]; then
    # Need to push
    return 2
  else
    # Diverged
    return 3
  fi
}

chown_configs() {
  if [ "${NGCP_TESTSUITE:-false}" = "true" ]; then
    log_debug "chown_configs: NGCP_TESTSUITE is set, skip step"
    return
  fi

  for f in ${NGCPCTL_CONFIG:-} ${NODE_CONFIG:-} ${PAIR_CONFIG:-} ${HOST_CONFIG:-} ${LOCAL_CONFIG:-} "${EXTRA_CONFIG_FILES[@]}" ${GLOB_CONFIG:-} ; do
    if [ ! -f "${f}" ]; then
      continue
    fi
    chown "${CONFIG_USER}":"${CONFIG_GROUP}" "${f}"
    chmod "${CONFIG_CHMOD}" "${f}"
  done
  if [ -f "${MAINTENANCE_CONFIG:-}" ]; then
    chown "${MAINTENANCE_CONFIG_USER}":"${MAINTENANCE_CONFIG_GROUP}" "${MAINTENANCE_CONFIG}"
    chmod "${MAINTENANCE_CONFIG_CHMOD}" "${MAINTENANCE_CONFIG}"
  fi
  if [ -f "${NETWORK_CONFIG:-}" ]; then
    chown "${NETWORK_CONFIG_USER}":"${NETWORK_CONFIG_GROUP}" "${NETWORK_CONFIG}"
    chmod "${NETWORK_CONFIG_CHMOD}" "${NETWORK_CONFIG}"
  fi
  if [ -f "${CONSTANTS_CONFIG:-}" ]; then
    chown "${CONSTANTS_CONFIG_USER}":"${CONSTANTS_CONFIG_GROUP}" "${CONSTANTS_CONFIG}"
    chmod "${CONSTANTS_CONFIG_CHMOD}" "${CONSTANTS_CONFIG}"
  fi
}

record_commit_id() {
  log_debug "cd ${NGCPCTL_MAIN}"
  cd "${NGCPCTL_MAIN}" || return

  log_debug "mkdir -p ${STATE_FILES_DIR}"
  mkdir -p "${STATE_FILES_DIR}"

  # if there are uncommitted changes then record it as such
  if git status --porcelain | grep -q . ; then
    echo "dirty" > "${STATE_FILES_DIR}/build"
  else
    local latest_commit
    latest_commit=$(git log -1 --format="%H")
    log_debug "echo ${latest_commit} > ${STATE_FILES_DIR}/build"
    echo "${latest_commit}" > "${STATE_FILES_DIR}/build"
  fi
}

is_git_clean() {
  log_debug "call 'git status --porcelain=v2'. it must have no output"
  if [ -z "$(git status --porcelain=v2)" ]; then
    return 0
  else
    return 1
  fi
}

check_maintenance_mode() {
  if [[ $(ngcpcfg get general.maintenance) == "yes" ]] ; then
    log_debug "ngcpcfg get general.maintenance == yes"
    return 0
  fi

  return 1
}

## }}}

## END OF FILE #################################################################
