#!/bin/bash
#
# Script to update the Jitsi-Meet stack
# Author: Leon Schroeder, Dominik Gedon
#--------------------------------------

# Uncomment to enable debugging
# set -x

BASENAME=jitsi
STACK=("meet" "videobridge" "jicofo" "jibri" "jigasi" )

# TODO:
# - only update changes and bump version if mkbuild and obsbuild are successful
# - rename directories to lowercase and simplify logic


### Functions ###

# Retrieves the source and packages it into an archive
get_source () {
	echo "Updating source file."
	FULL_NAME="$BASENAME-$1"
	# adjust the name
	REPO_NAME=$(get_repo_name $1)
	# there are no proper releases for those two so package the master branch instead
	if [ "$1" == "jibri" ] || [ "$1" == "jigasi" ];then
		BRANCH=master
	else
		BRANCH=$(curl --silent "https://api.github.com/repos/jitsi/$REPO_NAME/releases/latest" | jq -r .tag_name)
	fi
	curl --progress-bar -L https://github.com/jitsi/"$REPO_NAME"/tarball/"$BRANCH" > source.tar
	echo "Cloned $BRANCH."
	rm -rf /tmp/"$FULL_NAME" ||:
	mkdir /tmp/"$FULL_NAME"
	tar --strip-components=1 -xvf source.tar -C /tmp/"$FULL_NAME" &> /dev/null
	tar -cjvf "$FULL_NAME".tar.bz2 -C /tmp/ "$FULL_NAME" &> /dev/null
	rm -rf /tmp/"$FULL_NAME"  ||:
	rm source.tar
	echo "Repacked to $FULL_NAME.tar.bz2."
}

# bump the spec file version
bump_version () {
	echo "Bumping version in spec file."
	NAME=$BASENAME-$1
	# there are no proper releases for those two so take the jitsi-meet version number instead
	if [ "$1" == "jibri" ] || [ "$1" == "jigasi" ];then
		VERSION=$(curl --silent "https://api.github.com/repos/jitsi/jitsi-meet/releases/latest" | jq -r .name)
	else
		VERSION=$(curl --silent "https://api.github.com/repos/jitsi/$1/releases/latest" | jq -r .name)
	fi
	sed -i "0,/Version:/{s/Version:$PARTITION_COLUMN.*/Version:        $VERSION/}" "$NAME".spec
	echo "Updated spec file to version: $VERSION"
}

# update the .changes file
update_changes () {
	echo "Updating changelog."
	# adjust the name
	REPO_NAME=$(get_repo_name $1)
	NAME=$BASENAME-$1
	# there are no proper releases with changelogs for those two
	if [ "$1" == "jibri" ] || [ "$1" == "jigasi" ];then
		echo "No automated changelog generation possible. Please do it manually!"
	else
		wget -q "$(curl --silent "https://api.github.com/repos/jitsi/$REPO_NAME/releases/latest" | jq -r '.assets[] | select(.name | contains("CHANGELOG.txt")).browser_download_url')" -O- > tmp.changes
		sed -i '/^$/d' tmp.changes
		sed -i 's/* /- /g' tmp.changes
		cat tmp.changes <(echo) | cat - "$NAME".changes > temp && mv temp "$NAME".changes
		rm tmp.changes
	fi
}

# Get the name of the GitHub repository for the individual components
get_repo_name () {
	if [ "$1" == "meet" ] || [ "$1" == "videobridge" ];then
		echo "$BASENAME-$1"
	else
		echo "$1"
	fi
}

# move into the right directory.
change_dir () {
	NAME=$1
	cd .. || exit 1
	if [ -d "$BASENAME-$NAME" ]; then
		cd "$BASENAME-$NAME" || exit 1
	fi
}

# execute "build" or "version" for all packages
execute_all () {
	for item in ${STACK[*]};do
		"$1" "$item"
	done
}

# executes the Makefile
mkbuild () {
	echo "Executing Makefile."
	make || exit 1
}

# builds the package
obsbuild () {
	echo "Executing OBS build process."
	osc build --clean || exit 1
}

# retrieves the current version from the spec file
current_version () {
	change_dir "$1"
	TMP=$(grep 'Version:' "$BASENAME"-"$1".spec)
	VERSION=${TMP:(16)}
	echo "OBS version:      $VERSION"
}

# retrieves the most current upstream version
upstream_version () {
	# adjust the name
	REPO_NAME=$(get_repo_name $1)
	VERSION=$(curl --silent "https://api.github.com/repos/jitsi/$REPO_NAME/releases/latest" | jq -r .name)
	if [ "$VERSION" == "null" ];then
		# jigasi, jibri have no releases -> master
		echo "Upstream version: No proper release."
	else
		echo "Upstream version: $VERSION"
	fi
}

# install all build dependencies
dependencies () {
    echo "Installing build dependencies."
    npm install -g yarn webpack webpack-cli jetifier cross-os patch-package
}

# Show the version of one or more components
main_version () {
	if [ -z "$1" ];then
		# show version of all
		execute_all version
	else
		case $1 in
			jibri)
				version "$1"
				;;
			jicofo)
				version "$1"
				;;
			jigasi)
				version "$1"
				;;
			meet)
				version "$1"
				;;
			videobridge)
				version "$1"
				;;
			*)
				echo "If using a parameter, only the following are supported:"
				echo "${STACK[*]}"
				exit 1
				;;
		esac
	fi
}

# Build a single or all components
main_build () {
	if [ -z "$1" ];then
		# build all
		execute_all build
	else
		case $1 in
			jibri)
				build "$1"
				;;
			jicofo)
				build "$1"
				;;
			jigasi)
				build "$1"
				;;
			meet)
				build "$1" 
				;;
			videobridge)
				build "$1"
				;;
			*)
				echo "If using a stack, only the following are supported:"
				echo "${STACK[*]}"
				exit 1
				;;
		esac
	fi
}

help () {
    NAME=$BASENAME-update
    echo "Usage: $NAME OPTION [STACK]"
    echo "Helper script to update the Jitsi Meet stack."
    echo ""
    echo "OPTION"
    echo "  build       Build the package provided by STACK. If STACK is empty builds all packages."
    echo "  deps        Install the build dependencies."
	echo "  help        Print this help message."
    echo "  version     Check version numbers of the package provided with STACK."
	echo "              If STACK is empty shows version for all packages."
    echo ""
    echo "STACK"
    echo "${STACK[*]}"
    echo ""
    echo "Examples:"
    echo "  $NAME deps"
    echo "  $NAME build"
    echo "  $NAME build meet"
    echo "  $NAME version"
    echo "  $NAME version meet"
    echo ""
    echo "Note:"
    echo "Jibri and Jigasi have no proper releases. There the master branch will be taken as source and the version"
    echo "from Jitsi-Meet will be written to the spec file. Furthermore the changelog has to be done manually."
    exit 1

}

# version routine
version () {
	echo "$1:"
	upstream_version "$1"
	current_version "$1"
	echo "--------------------------"
}

# build routine
build () {
	echo "Building $1:"
	change_dir "$1"
	get_source "$1"
	mkbuild
	bump_version "$1"
	obsbuild
	update_changes "$1"
	echo "#-------------------------------"
}

### Main routine ###
case $1 in
    build)
        main_build $2
        ;;
    deps)
        dependencies
        ;;
    version)
        main_version $2
        ;;
    help | -h)
        help
        ;;
    *)
        help
        ;;
esac

