#!/usr/bin/env bash
#
# @license Apache-2.0
#
# Copyright (c) 2017 The Stdlib Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Builds and publishes API documentation.
#
# TODO:
#   1. Add support for specifying the project branch to build.
#   2. Generate log file similar to CircleCI build script.
#   3. Add support for specifying a commit message.
#   4. Add support for specifying a documentation branch.
#   5. Add support for specifying a documentation remote repository name.
#   6. Make determining a temporary build directory more robust. Ideally, we would use the `tmpdir` utility to build in the "proper" tmp directory.
#   7. Print total time elapsed for entire build sequence.
#


# VARIABLES #

# Project repository URL:
project_repo='https://github.com/stdlib-js/stdlib.git'

# The branch or release to checkout and from which to build project documentation:
project_checkout='develop'

# Documentation repository URL:
docs_repo='https://github.com/stdlib-js/www.git'

# Documentation repository name:
docs_repo_name='origin'

# The documentation repository remote branch to which to commit project documentation:
docs_checkout='master'

# Commit message when files are committed to documentation repository:
commit_message='Update documentation'

# Cache the working directory:
curr_dir="$PWD"

# Determine root directory:
root_dir="$(git rev-parse --show-toplevel)"

# Temporary directory for building documentation:
tmp_dir="${root_dir}/../tmp"

# Directory into which to clone the project repository:
project_dir="${tmp_dir}/project"

# Project documentation build directory:
project_build_dir="${project_dir}/build"

# Define the path to the project source library:
source_dir="${project_dir}/lib/node_modules"

# Define the path to the project utility for building API documentation:
build_docs="${source_dir}/@stdlib/_tools/docs/api/build-docs/bin/cli"

# Directory into which to clone the documentation repository:
docs_dir="${tmp_dir}/docs"


# FUNCTIONS #

# Defines an error handler.
#
# $1 - error status
on_error() {
	echo 'ERROR: An error was encountered during execution.' >&2
	cleanup
	exit "$1"
}

# Runs clean-up tasks.
cleanup() {
	cd "${curr_dir}"
	# remove_dir "${tmp_dir}"
}

# Creates a directory.
#
# $1 - directory path
create_dir() {
	mkdir -p "$1"
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to create directory: $1." >&2
		return 1
	fi
	echo "Created directory: $1." >&2
	return 0
}

# Removes a directory.
#
# $1 - directory path
remove_dir() {
	rm -rf "$1"
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to remove directory: $1." >&2
		return 1
	fi
	echo "Removed directory: $1." >&2
	return 0
}

# Moves a directory.
#
# $1 - directory to move
# $2 - output directory
move_dir() {
	mv "$1" "$2"
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to move directory $1 to $2." >&2
		return 1
	fi
	echo "Moved directory $1 to $2." >&2
	return 0
}

# Shallow clones a repository.
#
# $1 - repository URL
# $2 - output directory
shallow_clone() {
	git clone --depth=1 "$1" "$2"
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to clone repository: $1." >&2
		return 1
	fi
	echo "Cloned repository $1 to $2." >&2
	return 0
}

# Installs node module dependencies.
install_node_deps() {
	npm install
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to install node module dependencies." >&2
		return 1
	fi
	echo "Successfully installed node module dependencies." >&2
	return 0
}

# Prints a success message.
print_success() {
	echo 'Success!' >&2
}

# Main execution sequence:
main() {
	echo 'Creating temporary build directory...' >&2
	create_dir "${tmp_dir}"
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	echo 'Navigating to temporary build directory...' >&2
	cd "${tmp_dir}"

	echo 'Cloning project repository...' >&2
	shallow_clone "${project_repo}" "${project_dir}"
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	echo 'Navigating to project repository...' >&2
	cd "${project_dir}"

	echo "Switching to ${project_checkout}..." >&2
	git checkout "${project_checkout}"
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to switch to ${project_checkout} in the project repository." >&2
		on_error 1
	fi

	echo 'Returning to temporary build directory...' >&2
	cd "${tmp_dir}"

	echo 'Cloning documentation repository...' >&2
	shallow_clone "${docs_repo}" "${docs_dir}"
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	echo 'Navigating to documentation repository...' >&2
	cd "${docs_dir}"

	echo "Switching to ${docs_checkout}..." >&2
	git checkout "${docs_checkout}"
	if [[ "$?" -ne 0 ]]; then
		echo "Unable to switch to ${docs_checkout} in the documentation repository." >&2
		on_error 1
	fi

	echo 'Navigating to project repository...' >&2
	cd "${project_dir}"

	echo 'Installing project dependencies...' >&2
	install_node_deps
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	echo 'Building project documentation...' >&2
	NODE_PATH="${source_dir}" DEBUG='*' "${build_docs}"
	if [[ "$?" -ne 0 ]]; then
		echo 'Failed to successfully build project documentation.' >&2
		on_error 1
	fi

	echo 'Returning to temporary build directory...' >&2
	cd "${tmp_dir}"

	echo "If the documentation repository already has ${project_checkout} documentation, remove the existing documentation..." >&2
	remove_dir "${docs_dir}/public/${project_checkout}"
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	echo "Moving ${project_checkout} documentation to documentation repository..." >&2
	move_dir "${project_build_dir}/www/public/${project_checkout}" "${docs_dir}/public/${project_checkout}"
	if [[ "$?" -ne 0 ]]; then
		on_error 1
	fi

	echo 'Navigating to documentation repository...' >&2
	cd "${docs_dir}"

	echo 'Pulling latest changes...' >&2
	git pull "${docs_repo_name}" "${docs_checkout}"
	if [[ "$?" -ne 0 ]]; then
		echo 'Unable to pull down latest changes.' >&2
		on_error 1
	fi

	echo 'Committing files...' >&2
	git add -A
	if [[ "$?" -ne 0 ]]; then
		echo 'Unable to add files.' >&2
		on_error 1
	fi
	git commit -m "${commit_message}"
	if [[ "$?" -ne 0 ]]; then
		echo 'Unable to commit files.' >&2
		on_error 1
	fi

	echo 'Pushing to remote repository...' >&2
	git push "${docs_repo_name}" "${docs_checkout}"
	if [[ "$?" -ne 0 ]]; then
		echo 'Unable to push commits to remote.' >&2
		on_error 1
	fi

	print_success
	cleanup
	exit 0
}

# Run main:
main
