#!/bin/bash

# Check command line arguments and set options
# Run before loading configuration, to allow branch overriding
flag_INCREMENTAL="n"
flag_VERBOSE_LOG="n"
flag_SWITCH_ONLY="n"
OVERRIDE_DEFAULT_REPO_BRANCH=""
for ((idx=1; idx<=$#; idx++)); do
  arg="${!idx}"
	if [ "$arg" = "-i" ]; then 		    		# continue from last updated module (Incremental)
		flag_INCREMENTAL="y"
	elif [ "$arg" = "-v" ]; then 		    	# display and log git command output (Verbose)
		flag_VERBOSE_LOG="y"
	elif [ "$arg" = "-ub" ]; then 	   		# branches to update (Update Branches)
		((idx++))
		OVERRIDE_UPDATE_BRANCHES="${!idx}"
		[[ -z "$OVERRIDE_DEFAULT_REPO_BRANCH" ]] && OVERRIDE_DEFAULT_REPO_BRANCH="${!idx}"
	elif [ "$arg" = "-db" ]; then 	    	# default branch after update (Default Branch)
		((idx++))
		if [[ "$flag_SWITCH_ONLY" != 'y' ]]; then
		  # '-db' is only used if no '-so' argument is specified. If '-so <branch>'
		  # is given, '-db <branch> is ignored
			OVERRIDE_DEFAULT_REPO_BRANCH="${!idx}"
		fi
	elif [ "$arg" = "-so" ]; then 	   		# switch branch only (Switch Only)
		flag_SWITCH_ONLY="y" && ((idx++))
		OVERRIDE_DEFAULT_REPO_BRANCH="${!idx}"
	fi
done

# Load common code
. ./internals/_build_common.sh
init_common

UPDATE_LOCK_FILENAME="/var/lock/TDE_update_repo_lock"  	# Lock file for incremental update

declare -A RESULT_STRINGS=(
[OK]="[   OK   ]"
[FAIL]="[  FAIL  ]"
[UPDATE]="[ UPDATE ]"
[SKIP]="[  SKIP  ]"
[INV-OP]="[ INV-OP ]"
)
declare -A COLOR_STRINGS=(
[OK]="${CNone}"
[FAIL]="${CLightRed}"
[UPDATE]="${CLightGreen}"
[SKIP]="${CBrown}"
[INV-OP]="${CLightPurple}"
)

#----------------------------
# Update a given module from the upstream repo
# Parameters:
#  $1 - module folder
#  $2 - operation type
#  $3 - branch to update
function _do_update()
{
	local MOD_PATH=$1
	local OP_TYPE=$2
	local BRANCH=$3
	local RESULT=""
	local LINE_CTRL_SUFFIX=""
	
	case "$OP_TYPE" in
	  "fetch")
			if [[ -z `grep "^$BRANCH - $MOD_PATH$" "$UPDATE_LOCK_FILENAME"` ]]; then
				cd "$MOD_PATH" &>/dev/null
				eval git fetch --all --prune $GIT_NO_RECURSE_SUBMODULES $OPT_VERBOSE_LOG
				if [ $? -eq 0 ]; then
					RESULT="OK"
				else
					RESULT="FAIL"
				fi
				echo "$BRANCH - $MOD_PATH" >> "$UPDATE_LOCK_FILENAME"
			else
				RESULT="SKIP"
			fi
			;;
				

		"update")
			cd "$MOD_PATH" &>/dev/null
			if [ $? -eq 0 ]; then
				# Clean up any possible uncommitted changes
				if [[ ! -z "`git status --porcelain $GIT_IGNORE_SUBMODULES`" ]]; then
					git reset --hard HEAD &>/dev/null
					git clean -dxff &>/dev/null
				fi
				# Make sure the local branch exists
				if [[ -z `git branch | grep -E "\b$BRANCH\b"` ]]; then
					eval git checkout -b \"$BRANCH\" \"origin/$BRANCH\" $OPT_VERBOSE_LOG
				else
					eval git checkout \"$BRANCH\" $OPT_VERBOSE_LOG
				fi
				# Make sure the local branch is a tracking branch
				if [[ -z `git config branch."$BRANCH".remote` ]]; then
					git branch -u "origin/$BRANCH" &>/dev/null #$
					git reset --hard "origin/$BRANCH" &>/dev/null
				fi
				# Update
				eval git reset --hard HEAD $OPT_VERBOSE_LOG
				eval git clean -dxff $OPT_VERBOSE_LOG
				if [[ $(git rev-parse HEAD) != $(git rev-parse "origin/$BRANCH") ]]; then
					eval git rebase $OPT_VERBOSE_LOG
					if [[ `git rev-parse HEAD` == `git rev-parse "origin/$BRANCH"` ]]; then
						RESULT="UPDATE"
					else
						RESULT="FAIL"
					fi
				else
					RESULT="OK"
				fi
			else
				RESULT="FAIL"
			fi
			;;
		
		"switch-to")
			cd "$MOD_PATH" &>/dev/null
			eval git checkout \"$BRANCH\" $OPT_VERBOSE_LOG
			eval git reset --hard HEAD $OPT_VERBOSE_LOG
			eval git clean -dxff $OPT_VERBOSE_LOG
			if [[ ! -z `git branch -v | grep -E "^\*\s+$BRANCH"` ]]; then
				RESULT="OK"
			else
				RESULT="FAIL"
			fi
			;;
	
		*)
			RESULT="INV-OP"
			;;
	esac

	if [ "$RESULT" != "OK" -o "$flag_VERBOSE_LOG" = "y" ]; then
		LINE_CTRL_SUFFIX="\n"
	fi
	echo -ne "\033[2K\r${COLOR_STRINGS[$RESULT]}${RESULT_STRINGS[$RESULT]}  $MOD_PATH${CNone}$LINE_CTRL_SUFFIX"
	echo "${RESULT_STRINGS[$RESULT]}  $MOD_PATH" >> "$LOG_UPDATE_REPO_FILENAME"
}

#----------------------------
# Update a given module and all submodules from the upstream repo
# Parameters:
#  $1 - module folder
#  $2 - operation type 
#  $3 - branch to update
function _update_module()
{
	local MOD_PATH=$1
	local OP_TYPE=$2
	local BRANCH=$3
	
	# Current module
	_do_update "$@"
  # Submodules
  local SUBMOD_LIST="$MOD_PATH/.gitmodules"
	if [[ -e "$SUBMOD_LIST" ]]; then
		sed -n "s|^\[submodule \"\([^\"]*\)\"\]$|\1|p" <$SUBMOD_LIST |\
		while read -r SUBMOD_PATH; do
			cd "$MOD_PATH" &>/dev/null
			if [[ -z "`git config --get submodule.$SUBMOD_PATH.url`" ]]; then
				eval git submodule init -- \"$SUBMOD_PATH\" $OPT_VERBOSE_LOG
			fi
			if [[ ! -e "$MOD_PATH/$SUBMOD_PATH/.git" ]]; then
				eval git submodule update -- \"$SUBMOD_PATH\" $OPT_VERBOSE_LOG
			fi
			_update_module "$MOD_PATH/$SUBMOD_PATH" "$OP_TYPE" "$BRANCH"
		done
	fi
}

#----------------------------
if [ "$flag_INCREMENTAL" = "y" ]; then
  [ ! -f "$UPDATE_LOCK_FILENAME" ] && flag_INCREMENTAL="n"
else
	[ -f "$UPDATE_LOCK_FILENAME" ] && rm "$UPDATE_LOCK_FILENAME"
fi

OPT_VERBOSE_LOG="&>/dev/null"
if [[ "$flag_VERBOSE_LOG" = "y" ]]; then
	OPT_VERBOSE_LOG=" |& tee -a \"$LOG_UPDATE_REPO_FILENAME\""
fi

#----------------------------
# Check git abilities
GIT_IGNORE_SUBMODULES=""
if [[ -n "`git status --help 2>/dev/null|grep -- '--ignore-submodules'`" ]]; then
  GIT_IGNORE_SUBMODULES="--ignore-submodules"
fi
GIT_NO_RECURSE_SUBMODULES=""
if [[ -n "`git pull --help |grep -- '--\[no-\]recurse-submodules'`" ]]; then
  GIT_NO_RECURSE_SUBMODULES="--no-recurse-submodules"
fi

# Start update
if [ "$flag_INCREMENTAL" != "y" ]; then
	echo "TDE repositories update started" > "$UPDATE_LOCK_FILENAME"
fi

_LAST_BRANCH=""
if [[ "$flag_SWITCH_ONLY" != "y" ]]; then
	# Fetch all remotes first
	echo_and_tee "${CLightCyan}---------------------------------------${CNone}" "$LOG_UPDATE_REPO_FILENAME" "y"
	echo_and_tee "${CLightCyan}            Fetching remotes           ${CNone}" "$LOG_UPDATE_REPO_FILENAME"
	echo_and_tee "${CLightCyan}---------------------------------------${CNone}" "$LOG_UPDATE_REPO_FILENAME"
	
	# Fetch TDE main repository
	_update_module "$REPO_TDE" "fetch"
	
	echo -e "\033[2K"
	echo "" >> "$LOG_UPDATE_REPO_FILENAME"

	# Branch update
	for branch in "${BRANCHES[@]}"; do
		_LAST_BRANCH="$branch"
		echo_and_tee "${CLightCyan}---------------------------------------${CNone}" "$LOG_UPDATE_REPO_FILENAME"
		echo_and_tee "${CLightCyan}        Updating branch ${CYellow}$branch        ${CNone}" "$LOG_UPDATE_REPO_FILENAME"
		echo_and_tee "${CLightCyan}---------------------------------------${CNone}" "$LOG_UPDATE_REPO_FILENAME"
			
		# Update TDE main repository
		_update_module "$REPO_TDE" "update" "$branch"
		
		echo -e "\033[2K"
		echo "" >> "$LOG_UPDATE_REPO_FILENAME"
	done
fi

# Switch to specified branch if necessary
if [[ "$DEFAULT_REPO_BRANCH" != "$_LAST_BRANCH" ]]; then
	echo_and_tee "${CLightCyan}---------------------------------------${CNone}" "$LOG_UPDATE_REPO_FILENAME" "$flag_SWITCH_ONLY"
	echo_and_tee "${CLightCyan}      Switching to branch ${CYellow}$DEFAULT_REPO_BRANCH      ${CNone}" "$LOG_UPDATE_REPO_FILENAME"
	echo_and_tee "${CLightCyan}---------------------------------------${CNone}" "$LOG_UPDATE_REPO_FILENAME"
		
	# Switch TDE main repository
	_update_module "$REPO_TDE" "switch-to" "$DEFAULT_REPO_BRANCH"
	
	echo -e "\033[2K"
	echo "" >> "$LOG_UPDATE_REPO_FILENAME"
fi

# Update completed
[ -f "$UPDATE_LOCK_FILENAME" ] && rm "$UPDATE_LOCK_FILENAME"
cd $SCRIPT_DIR