#! /bin/bash
#
# @file         build.sh        Rebuild the dcp-client bundle without affecting
#                               the intermediate files in the dcp repo.
#
#                               Usage: build/bundle.sh <path to dcp repo>
#
# @author       Wes Garland, wes@distributive.network
# @date         Mar 2020
#

# portable implementation of linux realpath
realpath()
{
  (
    filename="$1"
    dirname="`dirname \"$1\"`"
    basename="`basename \"$1\"`"
    [ "$dirname" ] || dirname="."
    cd "$dirname" && echo "`pwd -P`/$basename"
  )
}

argvZero="$0"
argvRest="$*"
myDir="`dirname \`realpath $argvZero\``"

usage()
{
cat <<EOHELP

$0 - Rebuild the DCP-Client Bundle
Copyright (c) 2020-2024 Distributive Corp. All Rights Reserved.

Usage: $0 [path to dcp repo] [[--options] ... ]
Where:
  --help                      Shows this help
  --dcp=<dir>                 Sets the DCP source directory
  --build=<debug|release>     Sets the DCP build type
  --install-flags=<flags>     Sets extra flags used by dcp/install.sh
  -d or --debug               Debug the bundle-build process
  --reset                     Empty the invocation cache
  --no-cache                  Do not read or update the invocation cache
Note: Options will be cached as future invocations' defaults.
EOHELP
}

# Main program entry point
if [ "$1" ] && [ -d "$1" ]; then
  _DCP_SRC="$1"
  shift
fi

# pre-process args to scan for --no-cache
cd `dirname "$0"`/..
NO_CACHE=""
for opt in "$@"
do
  if [ "$opt" = "--no-cache" ]; then
    NO_CACHE=1
    echo " * Disabling cache" >&2
  fi
done

[ ! "${NO_CACHE}" ] && [ -f "${myDir}/etc/config.cache" ] && . "${myDir}/etc/config.cache" ]
[ "${_DCP_SRC}" ] && DCP_SRC="${_DCP_SRC}"

while getopts "dh-:" OPTION; do
  if [ "$OPTION" = "-" ]; then
    if [[ "$OPTARG" =~ (^[a-z0-9-]+)=(.*) ]]; then
      OPTION="${BASH_REMATCH[1]}"
      OPTARG="${BASH_REMATCH[2]}"
    else
      OPTION="${OPTARG}"
      OPTARG=""
    fi
  fi

  OPTFILES="`eval echo \"${OPTARG}\"`"
  [ -f "$OPTFILES" ] && OPTFILE="$OPTFILES" || OPTFILE=""

  case $OPTION in
    h|help)
      usage
      exit 1
      ;;
    dcp)
      DCP_SRC="${OPTARG}"
      ;;
    install-flags)
      DCP_INSTALL_FLAGS="${DCP_INSTALL_FLAGS} ${OPTARG}"
      ;;
    reset)
      rm -f "${myDir}/etc/config.cache"
      argvRest="`echo \"$argvRest\" | sed -e 's/--reset//' -e 's/^ *//'`"
      [ "$argvRest" ] && exec $SHELL -c "\"$argvZero\" $argvRest"
      exit 99
      ;;
    d|debug)
      DCP_INSTALL_FLAGS="${DCP_INSTALL_FLAGS} -d"
      DEBUG=1
      DEBUG_BUNDLE=1
      ;;
    build)
      [ "$DCP_BUILD" != "$OPTARGS" ] && echo "Setting DCP build type to ${OPTARG}"
      DCP_BUILD="${OPTARG}"
      ;;
    no-cache)
      ;;
    *)
      echo "Unrecognized option: $OPTION"
      exit 2
      ;;
  esac
done

DCP_SRC="`eval echo $DCP_SRC`"
if [ ! "$DCP_SRC" ] || [ ! -d "$DCP_SRC" ]; then
  echo "Could not locate DCP repo ($DCP_SRC). Once specified, it will be cached for future runs."
  echo "See $0 --help for more information. Stop."
  exit 98
else
  DCP_SRC="`realpath \"$DCP_SRC\"`"
fi >/dev/stderr

echo "Building DCP Client ${DCP_BUILD} bundle from DCP in ${DCP_SRC}"

case "${DCP_BUILD}" in
  debug|release)
  ;;
  *)
  echo "Unknown build type: ${DCP_BUILD}" >/dev/stderr
  exit 96
esac

# Write cache
[ -d "${myDir}/etc" ] || mkdir -p "${myDir}/etc"
if [ ! "${NO_CACHE}" ]; then
  cat > "${myDir}/etc/config.cache" << EOF
DCP_SRC="${DCP_SRC}"
DCP_INSTALL_FLAGS="${DCP_INSTALL_FLAGS}"
DCP_BUILD="${DCP_BUILD}"
EOF
fi

# Create staging folder so we don't make changes in dcp repo dist
BUNDLE_TMP="`mktemp -d -t XXXXX.dcpClientBuild`"
[ "$DEBUG_BUNDLE" ] || trap "rm -rf \"${BUNDLE_TMP}\"" EXIT
[ "$DEBUG_BUNDLE" ] && trap "echo 'Debug Mode: left \"$BUNDLE_TMP\" behind.'" EXIT
mkdir -p "${BUNDLE_TMP}/dist" || exit $?

# Write install.sh override files
cat > "${BUNDLE_TMP}/local-config.incl" <<EOF
echo " . Loading DCP local-config extras for dcp-client build/bundle" >&2
SRC_DIR="${DCP_SRC}"
DCP_PREFIX="${BUNDLE_TMP}"
BUILD="${DCP_BUILD}"
DCP_LOCAL_CONFIG_JSON="${BUNDLE_TMP}/local-config.json"
EOF

node > "${BUNDLE_TMP}/local-config.json" << EOJS
const localConfig = {};
localConfig.generated = "`date` by `id -un` on `hostname`";
if ("${DCP_BUILD}") localConfig.build = "${DCP_BUILD}";
localConfig.dcpClientDestination = "${BUNDLE_TMP}/dist";
console.log(JSON.stringify(localConfig));
EOJS

if [ ! -d "${DCP_SRC}/node_modules" ]; then
  echo "Cannot find ${DCP_SRC}/node_modules. Please run npm i from ${DCP_SRC}" >&2
  exit 97
fi

NO_LOG=1 \
SKIP_SUDO_CHECK=1 \
DCP_LOCAL_CONFIG_EXTRAS="${BUNDLE_TMP}/local-config.incl" \
  "${DCP_SRC}/install.sh" -N ${DCP_INSTALL_FLAGS} build-dcp-client

EXIT_CODE="$?"
if [ "$EXIT_CODE" != "0" ]; then
  echo "Error: ${DCP_SRC}/install.sh failed with code $EXIT_CODE. Stop." >&2
  exit 3
fi

echo
echo "Importing DCP Client Bundle"
cd "${myDir}/.."
[ "$?" = "0" ] || exit 4
[ "${DEBUG}" ] || [ "${DEBUG_BUNDLE}" ] && find "${BUNDLE_TMP}" -ls

(cd "${BUNDLE_TMP}" && tar -cf - ./dist) | tar -xvf - | sed 's/^/ - /'
STATUS=$?
echo "Done."
exit $STATUS
