#!/usr/bin/env bash


###########################
# Global Functions
###########################

function contains () {
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}

show_help ()
{
  echo ""
  echo "This downloads or updates the groot sources into /opt/groot."
  echo ""
  echo "    Usage:"
  echo "        groot_sources <required-options> <options>"
  echo "        groot_sources <required-options> <options> <space separated list of repos>"
  echo ""
  echo "    Repos: ecto ecl dslam navi bootstrap gopher concert desktop"
  echo ""
  echo "    Required Option (one of):"
  echo "        --stable                                        : work with the stable sources/binaries"
  echo "        --devel                                         : work with the devel sources/binaries"
  echo ""
  echo "    Options:"
  echo "        --help                                          : show this help message"
  echo "        --jobs=<n>                                      : parallelise downloads (default is 5)"
  echo "        --list                                          : list repo details"
  echo "        --delete                                        : delete workspaces"
  echo "        --update                                        : run wstool update on each workspace"
  echo "        --status                                        : run wstool status on each workspace"
  echo "        --branches                                      : show what branches are used in each workspace"
  echo "        -d, --source-directory=<directory>              : specify custom source directory"
  echo ""
  echo "    Admin Options:"
  echo "        --install                                       : set the install location to /opt/yujin/amd64/xxx for all workspaces"
  echo ""
  exit 0
}

###########################
# PreConfigured Defaults
###########################

JOBS=5

###########################
# Command Line
###########################

for i in "$@"
do
case $i in
    --help)
    SHOW_HELP=1
    shift
    ;;
    --delete)
    DELETE=1
    shift
    ;;
    --install)
    INSTALL_STRING="--install=/opt/yujin/indigo"
    shift
    ;;
    --update)
    UPDATE=1
    shift
    ;;
    --list)
    SHOW_REPOS=1
    shift
    ;;
    --status)
    SHOW_STATUS=1
    shift
    ;;
    --branches)
    SHOW_BRANCHES=1
    shift
    ;;
    --stable)
    STABLE=1
    shift
    ;;
    --devel)
    DEVEL=1
    shift
    ;;
    -j=*|--jobs=*)
    JOBS="${i#*=}"
    shift
    ;;
    -d=*|--source-directory=*)
    USE_CUSTOM_SOURCE_DIRECTORY=1
    CUSTOM_SOURCE_DIRECTORY="${i#*=}"
    shift
    ;;
    *)
       # unknown option
    ;;
esac
done

###########################
# Early Aborts
###########################

if [ ! -z "$SHOW_HELP" ]; then
  show_help
  exit 0
fi

if [ ! -z "${ROS_MASTER_URI}" ]; then
  echo "    This is a ros environment, you must run this script from a non-ros environment (new shell)."
  exit 1
fi

if [ -z "$STABLE" ] && [ -z "$DEVEL" ]; then
  echo ""
  echo "    You must set one of either --stable or --devel."
  echo "        Run with --help for more information."
  echo ""
  exit 1
fi

###########################
# Variables
###########################

if [ ! -z "$STABLE" ]; then
  RELEASE="stable"
  WS="stable_ws"
else
  RELEASE="devel"
  WS="ws"
fi

if [ ! -z "$USE_CUSTOM_SOURCE_DIRECTORY" ]; then
  GROOT=$CUSTOM_SOURCE_DIRECTORY
else
  GROOT=/opt/groot
fi

ALL_REPOS=("ecto" "ecl" "dslam" "navi" "bootstrap" "gopher" "concert" "desktop")
declare -A ALL_REPO_KEYS
declare -A ALL_UNDERLAYS

ALL_REPO_KEYS=( ["ecto"]="ecto-${RELEASE}" ["ecl"]="ecl-${RELEASE}" ["bootstrap"]="gopher_bootstrap-${RELEASE}" ["concert"]="gopher_concert-${RELEASE}" ["navi"]="gopher_navigation-${RELEASE}" ["dslam"]="gopher_dslam-${RELEASE}" ["gopher"]="gopher-${RELEASE}" ["desktop"]="gopher_desktop-${RELEASE}" )

E_CLOUD="${GROOT}/ecl_${WS}/devel;${GROOT}/ecto_${WS}/devel"
DSLAM_CLOUD="${GROOT}/dslam_${WS}/devel;${E_CLOUD}"
NAVI_CLOUD="${GROOT}/navi_${WS}/devel;${DSLAM_CLOUD}"
BOOTSTRAP_CLOUD="${GROOT}/bootstrap_${WS}/devel;${NAVI_CLOUD}"
SOFTWARE_CLOUD="${GROOT}/concert_${WS}/devel;${BOOTSTRAP_CLOUD}"

ALL_UNDERLAYS=( ["ecto"]="" ["ecl"]="" ["dslam"]="${E_CLOUD}" ["navi"]="${DSLAM_CLOUD}" ["bootstrap"]="${NAVI_CLOUD}" ["concert"]="${BOOTSTRAP_CLOUD}" ["gopher"]="${BOOTSTRAP_CLOUD}" ["desktop"]="${SOFTWARE_CLOUD}")

REPOS=()

if [ "$#" -gt 0 ]; then
  for var in "$@"
  do
    REPOS+=($var)
  done
else
  for repo in "${ALL_REPOS[@]}"
  do
    REPOS+=($repo)
  done
fi

###########################
# Functions
###########################

show_repos ()
{
  for repo in "${ALL_REPOS[@]}"
  do
    echo "${repo}"
    echo "  rosinstall key: ${ALL_REPO_KEYS[${repo}]}"
    echo "  underlays     : ${ALL_UNDERLAYS[${repo}]};/opt/yujin/indigo"
  done
}

download_sources ()
{
  echo "Downloading groot."
  for repo in "${REPOS[@]}"; do
  #for ((i=0;i<${#REPOS[@]};++i)); do
    cd ${GROOT}
    if contains ${repo} ${ALL_REPOS[@]}; then
      if [ -d "${GROOT}/${repo}_${WS}" ]; then
	echo "  Workspace ${GROOT}/${repo}_${WS} already exists, skipping, remove manually or use --delete."
      else
	echo "  Downloading ${repo}."
	yujin_init_workspace -j${JOBS} ${repo}_${WS} ${ALL_REPO_KEYS[${repo}]}
	cd ${GROOT}/${repo}_${WS}
	echo "  Configuring ${repo}."
	yujin_init_build --underlays="${ALL_UNDERLAYS[${repo}]};/opt/yujin/amd64/indigo-${RELEASE}" ${INSTALL_STRING} .
      fi
    else
      echo ""
      echo "ERROR : ${repo} is not a valid workspace, choose from"
      echo "      :   [${ALL_REPOS[@]}]"
      echo ""
    fi
  done
  echo ""
  echo "You may need an additional 'groot_binaries --${RELEASE} --install-rosdeps' if there are new dependencies."
  echo ""
}

update_sources ()
{
  echo "Updating groot."
  for ((i=0;i<${#REPOS[@]};++i)); do
    repo=${REPOS[i]}
    repo_key=${ALL_REPO_KEYS[${repo}]}
    if contains ${repo} ${ALL_REPOS[@]}; then
      if [ ! -d "${GROOT}/${repo}_${WS}" ]; then
	echo "${repo} not found, redownloading."
	cd ${GROOT}
	echo "  Downloading ${repo}."
	yujin_init_workspace -j${JOBS} ${repo}_${WS} ${repo_key}
	cd ${GROOT}/${repo}_${WS}
	echo "  Configuring ${repo}."
	yujin_init_build --underlays="${ALL_UNDERLAYS[${repo}]};/opt/yujin/amd64/indigo-${RELEASE}" .
      fi
      cd ${GROOT}/${repo}_${WS}
      echo "  Updating ${repo} from ${repo_key}"
      echo ""
      echo "       yujin_init_workspace -j${JOBS} --merge ${repo_key}"
      echo ""
      yujin_init_workspace -j${JOBS} --merge ${repo_key}
    else
      echo ""
      echo "ERROR : ${repo} is not a valid workspace, choose from"
      echo "      :   [${ALL_REPOS[@]}]"
      echo ""
    fi
  done
  echo ""
  echo "You may need an additional 'groot_binaries --${RELEASE} --install-rosdeps' if there are new dependencies."
  echo ""
}

show_branches ()
{
  echo "******************************************************"
  echo "* Showing branch information of repositories in groot."
  echo "******************************************************"
  for repo in ${REPOS[*]}; do
    if [ -d "${GROOT}/${repo}_${WS}/src" ]; then
      cd ${GROOT}/${repo}_${WS}/src
      echo "****************************"
      echo "* ${repo}"
      echo "****************************"
      yujin_list_git_branches
    fi
  done
}

show_status ()
{
  echo "Showing status of repos in groot."
  for repo in ${REPOS[*]}; do
    if [ -d "${GROOT}/${repo}_${WS}/src" ]; then
      echo "  Status of ${repo}:"
      cd ${GROOT}/${repo}_${WS}/src
      wstool status
    fi
  done
}

mkdir_groot ()
{
  if [ ! -d "${GROOT}" ]; then
    mkdir ${GROOT}
    if [ "$?" == "1" ]; then
      echo "Could not create the groot directory (check permissions)."
      exit 1
    fi
  fi
}

delete_sources ()
{
  echo "Deleting workspaces."
  for repo in "${REPOS[@]}"; do
    if [ -d "${GROOT}/${repo}_${WS}" ]; then
      echo "  Deleting ${GROOT}/${repo}_${WS}."
      rm -rf ${GROOT}/${repo}_${WS}
    fi
  done
}

###########################
# Workers
###########################

if [ ! -z "$SHOW_REPOS" ]; then
  show_repos
  exit 0
fi

if [ ! -z "$SHOW_STATUS" ]; then
  if [ ! -d "${GROOT}" ]; then
    echo "No groot workspaces found."
  else
    show_status
  fi
  exit 0
fi

if [ ! -z "$SHOW_BRANCHES" ]; then
  if [ ! -d "${GROOT}" ]; then
    echo "No groot workspaces found."
  else
    show_branches
  fi
  exit 0
fi

if [ ! -z "$DELETE" ]; then
  delete_sources
  exit 0
fi

if [ ! -z "${UPDATE}" ]; then
  update_sources
  exit 0
fi

mkdir_groot
download_sources

