#!/bin/bash -e

### @accetto, December 2020
### https://github.com/accetto/ubuntu-vnc-xfce-g3
### https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki

# ARG_VERSION([echo $0 v22.11.04])
# ARG_HELP([Utility for previewing README files intended for Docker Hub. The prepared files can be manually copy-and-pasted to Docker Hub. The utility should be run from the '/utils' directory.])
#
# ARG_POSITIONAL_SINGLE([command],[Command to execute. Available commands: \n \
# cleanup - Deletes the previously generated README preview and other helper files. \n \
#           This is the default command if both <command> and <repo> are empty. \n \
# preview - Generates the README preview file and checks its length. \n \
#           This is the default command if <command> is empty, but <repo> is not. \n \
#],[""])
#
# ARG_DEFAULTS_POS([])
# ARG_POSITIONAL_DOUBLEDASH([])
#
# ARG_OPTIONAL_SINGLE([repo],[],[Target Docker Hub repository (owner/repo)],[""])
# ARG_OPTIONAL_SINGLE([context],[],[Path to the readme files (relative to '/utils', e.g. '../docker/xfce')],[""])
# ARG_OPTIONAL_SINGLE([readme],[],[Readme file main part name],[README-dockerhub.md])
# ARG_OPTIONAL_SINGLE([template],[],[Readme appendix template file name],[readme-append.template])
# ARG_OPTIONAL_SINGLE([limit],[],[Max. length of the final README file in bytes (max. 25000)],[25000])
# ARG_OPTIONAL_SINGLE([gist],[],[Gist ID containing off-line metadata (e.g. badge endpoints)(alternatively set 'DEPLOY_GIST_ID' environment variable)])
#
# ARGBASH_GO()
# needed because of Argbash --> m4_ignore([
### START OF CODE GENERATED BY Argbash v2.10.0 one line above ###
# Argbash is a bash code generator used to get arguments parsing right.
# Argbash is FREE SOFTWARE, see https://argbash.dev for more info


die()
{
	local _ret="${2:-1}"
	test "${_PRINT_HELP:-no}" = yes && print_help >&2
	echo "$1" >&2
	exit "${_ret}"
}


begins_with_short_option()
{
	local first_option all_short_options='vh'
	first_option="${1:0:1}"
	test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
}

# THE DEFAULTS INITIALIZATION - POSITIONALS
_positionals=()
_arg_command=""
# THE DEFAULTS INITIALIZATION - OPTIONALS
_arg_repo=""
_arg_context=""
_arg_readme="README-dockerhub.md"
_arg_template="readme-append.template"
_arg_limit="25000"
_arg_gist=


print_help()
{
	printf '%s\n' "Utility for previewing README files intended for Docker Hub. The prepared files can be manually copy-and-pasted to Docker Hub. The utility should be run from the '/utils' directory."
	printf 'Usage: %s [-v|--version] [-h|--help] [--repo <arg>] [--context <arg>] [--readme <arg>] [--template <arg>] [--limit <arg>] [--gist <arg>] [--] [<command>]\n' "$0"
	printf '\t%s\n' "<command>: Command to execute. Available commands:
		 \
# cleanup - Deletes the previously generated README preview and other helper files.
		 \
#           This is the default command if both <command> and <repo> are empty.
		 \
# preview - Generates the README preview file and checks its length.
		 \
#           This is the default command if <command> is empty, but <repo> is not.
		 \
# (default: '""')"
	printf '\t%s\n' "-v, --version: Prints version"
	printf '\t%s\n' "-h, --help: Prints help"
	printf '\t%s\n' "--repo: Target Docker Hub repository (owner/repo) (default: '""')"
	printf '\t%s\n' "--context: Path to the readme files (relative to '/utils', e.g. '../docker/xfce') (default: '""')"
	printf '\t%s\n' "--readme: Readme file main part name (default: 'README-dockerhub.md')"
	printf '\t%s\n' "--template: Readme appendix template file name (default: 'readme-append.template')"
	printf '\t%s\n' "--limit: Max. length of the final README file in bytes (max. 25000) (default: '25000')"
	printf '\t%s\n' "--gist: Gist ID containing off-line metadata (e.g. badge endpoints)(alternatively set 'DEPLOY_GIST_ID' environment variable) (no default)"
}


parse_commandline()
{
	_positionals_count=0
	while test $# -gt 0
	do
		_key="$1"
		if test "$_key" = '--'
		then
			shift
			test $# -gt 0 || break
			_positionals+=("$@")
			_positionals_count=$((_positionals_count + $#))
			shift $(($# - 1))
			_last_positional="$1"
			break
		fi
		case "$_key" in
			-v|--version)
				echo $0 v22.11.04
				exit 0
				;;
			-v*)
				echo $0 v22.11.04
				exit 0
				;;
			-h|--help)
				print_help
				exit 0
				;;
			-h*)
				print_help
				exit 0
				;;
			--repo)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_repo="$2"
				shift
				;;
			--repo=*)
				_arg_repo="${_key##--repo=}"
				;;
			--context)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_context="$2"
				shift
				;;
			--context=*)
				_arg_context="${_key##--context=}"
				;;
			--readme)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_readme="$2"
				shift
				;;
			--readme=*)
				_arg_readme="${_key##--readme=}"
				;;
			--template)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_template="$2"
				shift
				;;
			--template=*)
				_arg_template="${_key##--template=}"
				;;
			--limit)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_limit="$2"
				shift
				;;
			--limit=*)
				_arg_limit="${_key##--limit=}"
				;;
			--gist)
				test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
				_arg_gist="$2"
				shift
				;;
			--gist=*)
				_arg_gist="${_key##--gist=}"
				;;
			*)
				_last_positional="$1"
				_positionals+=("$_last_positional")
				_positionals_count=$((_positionals_count + 1))
				;;
		esac
		shift
	done
}


handle_passed_args_count()
{
	test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1
}


assign_positional_args()
{
	local _positional_name _shift_for=$1
	_positional_names="_arg_command "

	shift "$_shift_for"
	for _positional_name in ${_positional_names}
	do
		test $# -gt 0 || break
		eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
		shift
	done
}

parse_commandline "$@"
handle_passed_args_count
assign_positional_args 1 "${_positionals[@]}"

# OTHER STUFF GENERATED BY Argbash

### END OF CODE GENERATED BY Argbash (sortof) ### ])
# [ <-- needed because of Argbash

### #####################
### USER CODE BEGINS HERE
### #####################

dump_args() {

    printf "Value of '%s': %s\\n" 'command' "${_arg_command}"
    printf "Value of '%s': %s\\n" 'repo' "${_arg_repo}"
    printf "Value of '%s': %s\\n" 'context' "${_arg_context}"
    printf "Value of '%s': %s\\n" 'readme' "${_arg_readme}"
    printf "Value of '%s': %s\\n" 'template' "${_arg_template}"
    printf "Value of '%s': %s\\n" 'limit' "${_arg_limit}"
    printf "Value of '%s': %s\\n" 'gist' "${_arg_gist}"
}

do_cleanup() {

	rm -f "${_scrap_append_file}" "${_readme_upload_file}"
	echo "Cleanup finished."
}

do_preview() {

	local repo="${_arg_repo}"
	local readme_context="${_arg_context}"
	local readme_main="${_arg_readme}"
	local readme_append="${_arg_template}"
	local gist="${_arg_gist:-${DEPLOY_GIST_ID}}"

	local readme_append_file
	local readme_main_file
	local repo_name
    local repo_owner

	local -i size
	local -i delta

	if [[ -z ${_arg_repo} ]] ; then

		die "Repository (owner/repo) must be provided."
	fi

	if [[ -z "${readme_context}" ]] ; then

		die "Readme context must be provided."
	fi

	if [[ -z "${readme_main}" ]] ; then

		die "Readme main part file name must be provided."
	fi

    readme_main_file="${readme_context}/${readme_main}"

	if [[ ! -f "${readme_main_file}" ]] ; then

		die "Missing readme main part file: '${readme_main_file}' "
	fi

	### readme appendix template is optional
	if [[ -n "${readme_append}" ]] ; then

		readme_append_file="${readme_context}/${readme_append}"

		if [[ ! -f "${readme_append_file}" ]] ; then

			die "Missing readme appendix template file: '${readme_append_file}' "
		fi

		if [[ -z "${gist}" ]] ; then

			die "Deployment gist ID must provided as a parameter or 'DEPLOY_GIST_ID' environment variable!"
		fi
	fi

	### extract the repo owner and its name
    ### alternative 1
    repo_name="$(basename $repo)"
    repo_owner="$(basename $(dirname ${repo}))"
    ### alternative 2
    # repo_name="${repo##*/}"
    # repo_owner="${repo%$repo_name}" ; repo_owner="${repo_owner::-1}" ; repo_owner="${repo_owner##*/}"
    ### also ensure that the deployment repo has only two parts like 'repo_owner/repo_name'
    # _deployment_repo="$(basename $(dirname ${repo}))/$(basename ${repo})"
    _deployment_repo="${repo_owner}/${repo_name}"

	### create the actual README file for Docker Hub by replacing the variables in the append-template (badge links)
    ### and appending it to the main-readme partial file
    ### it is expected that the readme include template contains the following variables:
    ### ${OWNER}    - owner of the deployment repository and also the related deployment gist
    ### ${GIST}     - gist containing the badge endpoints
    ### ${REPO}     - name of the deployment repository

	### readme appendix templating is optional
	if [[ -n "${readme_append}" ]] ; then

		### replace the environment variables in the template
		( OWNER="${repo_owner}" GIST="${gist}" REPO="${repo_name}" envsubst < "${readme_append_file}" > "${_scrap_append_file}" )

		### append the updated template to the main readme part
		cat "${readme_main_file}" "${_scrap_append_file}" > "${_readme_upload_file}"
		rm -f "${_scrap_append_file}"
	else
		### no appendix and no templating
		cp "${readme_main_file}" "${_readme_upload_file}"
	fi

	echo "Readme preview: ${_readme_upload_file} "

	size=$( wc --bytes "${_readme_upload_file}" | awk '{print $1}' )
	delta=$((_arg_limit-size))
	echo "Readme length is ${size} bytes, leaving ${delta} bytes available (max. ${_arg_limit}). "

}

main() {

    ### just debugging support
    # dump_args
	case ${_arg_command,,} in

		cleanup )
			do_cleanup "${_scrap_append_file}" "${_readme_upload_file}"
			;;

		preview )
			do_cleanup "${_scrap_append_file}" "${_readme_upload_file}"
			do_preview
			;;

		* )
			if [[ -z "${_arg_command}" ]] ; then

				if [[ -z "${_arg_repo}" ]] ; then

					do_cleanup
				else
					do_preview
				fi
			else
				die "Unsupported command '${_arg_command}' "
			fi
			;;
	esac
}

### ################
### MAIN ENTRY POINT
### ################

declare _current_dir
declare _deployment_repo
declare _readme_upload_file
declare _scrap_append_file

_current_dir=$(dirname $0)

_scrap_append_file="${_current_dir}/scrap-append.tmp"
_readme_upload_file="${_current_dir}/scrap-readme.md"

main

# ] <-- needed because of Argbash
