#!/bin/bash
# Purpose: detect modified files in config tree and execute
#          any defined service modifications
################################################################################

set -e
set -u

# support testsuite
FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}"

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

. "${FUNCTIONS}"/main

# main script

DRYRUN='false'
if [[ "${1:-}" == "test" ]] || [[ "${1:-}" == "--dry-run" ]]; then
  DRYRUN='true'
elif [[ -n "${1:-}" ]] ; then
  log_error "Unsupported option(s) given: $*"
  log_info  "Did you mean '--dry-run'?"
  exit 1
fi
log_debug "DRYRUN = $DRYRUN"

TMPFILE="$(mktemp)"
log_debug "TMPFILE = $TMPFILE"

# unify service calls
unifyer() {
  file="$1"

  # make sure services are listed just once to
  # avoid re-execution of services (which will
  # happen if /etc/foo/ngcpcfg.services exists
  # and several file inside /etc/foo are modified)
  if ! grep -q "^${file}$" "$TMPFILE" ; then
    echo "$file" >> "$TMPFILE"
  fi
}

for dir in ${CONFIG_POOL} ; do
  #shellcheck disable=SC2106
  (
  if ! [[ "${dir}" =~ ^/ ]] ; then
    log_error "${dir} is not an absolute path"
    continue
  fi
  cd "${dir}"
  if [ ! -d .git ] ; then
    log_info "$dir has no support of .services"
    continue
  fi
  for file in $(git status --porcelain | sed 's/^...//') ; do
    if [ -r "$file" ] && [ -r "${SERVICES_POOL_BASE}/${dir}/${file}".services ] ; then
      log_debug "unifyer ${SERVICES_POOL_BASE}/${dir}/${file}.services"
      unifyer "${SERVICES_POOL_BASE}/${dir}/${file}".services
    elif [ -r "$file" ] && [ -r "${SERVICES_POOL_BASE}/${dir}/$(dirname "$file")"/ngcpcfg.services ] ; then
      log_debug "unifyer ${SERVICES_POOL_BASE}/${dir}/$(dirname "$file")/ngcpcfg.services"
      unifyer "${SERVICES_POOL_BASE}/${dir}/$(dirname "$file")/ngcpcfg.services"
    fi
  done
  )
done

exec_wrapper() {
  if $DRYRUN ; then
    log_info "TEST MODE: Would execute action for ${line}"
    return 0
  fi

  log_info "Executing action for $line"
  if [ -x "$line" ] ; then
    log_debug "$line"
    if ! "$line" ; then
      log_warn "$line returned with error code, continuing anyway."
    fi
  elif [ -r "$line" ] ; then
    log_debug "bash $line"
    if ! bash "$line" ; then
      log_warn "$line returned with error code, continuing anyway."
    fi
  else
    log_error "Error: $line could not be read."
    exit 1
  fi
}

if ! [ -s "$TMPFILE" ] ; then
  log_debug "No services file(s) reported - nothing to do."
  exit 0
fi

# get rid of "./" and "//" in file names
normalize_files() {
  NORMALIZED_FILES="$(mktemp)"
  log_debug "NORMALIZED_FILES = $NORMALIZED_FILES"

  while read line ; do
    # shellcheck disable=SC2001
    echo "$line" | sed -e 's_\./_/_g ; s_//_/_g' >> "${NORMALIZED_FILES}"
  done < "$TMPFILE"
}

# restart monit services before the rest (see MT#9971)
# restart HA just after monit (see MT#17163)
sort_service_list() {
  SORTED_LIST="$(mktemp)"
  log_debug "SORTED_LIST = $SORTED_LIST"

  grep "${SERVICES_POOL_BASE}"/etc/monit/'.*services' "${NORMALIZED_FILES}" > \
    "${SORTED_LIST}" || true
  grep "${SERVICES_POOL_BASE}"/etc/ha.d/'.*services' "${NORMALIZED_FILES}" >> \
    "${SORTED_LIST}" || true
  grep -v "${SERVICES_POOL_BASE}"/etc/monit/'.*services' "${NORMALIZED_FILES}"| \
    grep -v "${SERVICES_POOL_BASE}"/etc/ha.d/'.*services' >> \
    "${SORTED_LIST}" || true
}

execute() {
  while read line ; do
    exec_wrapper "$line"
  done < "${SORTED_LIST}"
}

log_debug "normalize_files function"
normalize_files

log_debug "sort_service_list function"
sort_service_list

log_debug "execute function"
execute

if [ -n "${DEBUG:-}" ] ; then
  log_debug "Not removing temporary files"
else
  rm -f "$TMPFILE" "$NORMALIZED_FILES" "$SORTED_LIST"
fi
## END OF FILE #################################################################
