#!/bin/bash

declare	BOOTSTRAP_DIR=$(dirname "$0")

unset PMODULES_ROOT
unset PMODULES_HOME
unset PMODULES_VERSION
unset PMODULES_DISTFILESDIR

source "${BOOTSTRAP_DIR}/Pmodules/libstd.bash"

declare -r BOOTSTRAP_DIR=$(std::get_abspath "${BOOTSTRAP_DIR}")
declare -r SRC_DIR="${BOOTSTRAP_DIR}/Pmodules"

usage() {
	echo "
build [OPTIONS] configure|compile|install
"
	std::die 1 ""
}

declare -rx DEFAULT_PMODULES_ROOT='/opt/psi'
declare -rx DEFAULT_PMODULES_DISTFILESDIR="${DEFAULT_PMODULES_ROOT}/var/distfiles"
declare -rx DEFAULT_CONFIG_FILE='config/modbuild.conf'
declare -rx DEFAULT_PMODULES_TMPDIR='/var/tmp/${USER}'

#-----------------------------------------------------------------------------
#
pmodules::configure() {
	local install_root="${DEFAULT_PMODULES_ROOT}"
	local distfilesdir="${DEFAULT_PMODULES_DISTFILESDIR}"
	local tmpdir="${DEFAULT_PMODULES_TMPDIR}"
	local config_file="${BOOTSTRAP_DIR}/${DEFAULT_CONFIG_FILE}"

	while (( $# > 0 )); do
		case "$1" in
			--config )
				config_file="$2"
				shift 1
				;;
			--config=* )
				config_file="${1#*=}"
				;;
			--install-root )
				install_root="$2"
				shift 1
				;;
			--install-root=* )
				install_root="${1#*=}"
				;;
			--distfilesdir )
				distfilesdir="$2"
				shift 1
				;;
			--distfilesdir=* )
				distfilesdir="${1#*=}"
				;;
			--tmpdir )
				tmpdir="$2"
				shift 1
				;;
			--tmpdir=* )
				tmpdir="${1#*=}"
				;;
			-* )
				std::die 1 "$1: illegal option"
				;;
			* )
				std::die 1 "$1: illegal argument to sub-command 'configure'."
				;;
		esac
		shift 1
	done

	sed_cmd="s:@PMODULES_ROOT@:${install_root}:g;"
	sed_cmd+="s:@PMODULES_DISTFILESDIR@:${distfilesdir}:g;"
	sed_cmd+="s:@PMODULES_TMPDIR@:${tmpdir}:g;"

	sed "${sed_cmd}" "${DEFAULT_CONFIG_FILE}.in" > "${config_file}"
}

#-----------------------------------------------------------------------------
#
pmodules::compile() {
	build () {
		local -r name="$1"
		local -r version="$2"
		shift 2

		"${BOOTSTRAP_DIR}/Pmodules/modbuild" \
			"${BOOTSTRAP_DIR}/${name}/build" \
			"${build_opts[@]}" "$@" "${version}" || \
			std::die 3 "Compiling '${name}' failed!"
	}

	local force='no'
	local config_file="${BOOTSTRAP_DIR}/${DEFAULT_CONFIG_FILE}"

	while (( $# > 0 )); do
		case $1 in
			--disable-cleanup )
				build_opts+=( "$1" )
				;;
			--debug )
				build_opts+=( "$1" )
				;;
			--config )
				config_file="$2"
				shift 1
				;;
			--config=* )
				config_file="${1#*=}"
				;;
			--install-root )
				PMODULES_ROOT="$2"
				shift 1
				;;
			--install-root=* )
				PMODULES_ROOT="${1#*=}"
				;;
			-f | --force )
				force='yes'
				;;
			-* )
				std::die 1 "$1: illegal option"
				;;
			* )
				std::die 1 "$1: illegal argument for  sub-command 'compile'."
				;;
		esac
		shift 1
	done

	std::read_versions "${BOOTSTRAP_DIR}/config/versions.conf"
	source "${config_file}"

	if [[ ! -f "${PMODULES_HOME}/sbin/base64" ]] || [[ ${force} == 'yes' ]]; then
		build coreutils "${COREUTILS_VERSION}"
	fi

	if [[ ! -f "${PMODULES_HOME}/sbin/xgettext" ]] || [[ ${force} == 'yes' ]]; then
		build gettext "${GETTEXT_VERSION}"
	fi

	if [[ ! -f "${PMODULES_HOME}/sbin/getopt" ]] || [[ ${force} == 'yes' ]]; then
		build getopt "${GETOPT_VERSION}"
	fi

	if [[ ! -f "${PMODULES_HOME}/sbin/bash" ]] || [[ ${force} == 'yes' ]]; then
		build bash "4.3.30"
	fi

	if [[ ! -e "${PMODULES_HOME}/sbin/tclsh" ]] || [[ ${force} == 'yes' ]]; then
		build Tcl "${TCL_VERSION}"
	fi

	if [[ ! -e "${PMODULES_HOME}/libexec/modulecmd.bin" ]] || [[ ${force} == 'yes' ]]; then
		build modules "${MODULES_VERSION}"
	fi
	echo "Done..."
}

#-----------------------------------------------------------------------------
#
pmodules::install() {
	local opt_force='no'
	local config_file="${BOOTSTRAP_DIR}/${DEFAULT_CONFIG_FILE}"

	while (( $# > 0 )); do
		case $1 in
			--debug )
				set -x
				;;
			--config )
				config_file="$2"
				shift 1
				;;
			--config=* )
				config_file="${1#*=}"
				;;
			--debug )
				set -x
				;;
			--install-root )
				PMODULES_ROOT="$2"
				shift 1
				;;
			--install-root=* )
				PMODULES_ROOT="${1#*=}"
				;;
			-f | --force )
				opt_force='yes'
				;;
			-* )
				std::die 1 "$1: illegal option"
				;;
			* )
				std::die 1 "$1: illegal argument to sub-command 'install'."
				;;
		esac
		shift 1
	done

	std::read_versions "${BOOTSTRAP_DIR}/config/versions.conf"
	source "${config_file}"

	if [[ ! -d "${PMODULES_ROOT}" ]]; then
		read -p "The requested root directory does not exist. Create it? [y|N] " -n 1 ans
		case ${ans} in 
		y | Y )
			mkdir -p "${PMODULES_ROOT}"
			;;
		* )
			echo "Aborting ..." 1>&2
			exit 2
			;;
		esac
	fi

	###
	#
	# begin installation
	#
	echo "Installing to ${PMODULES_HOME} ..."
	sed_cmd="s:@PMODULES_HOME@:${PMODULES_HOME}:g;"
	sed_cmd+="s:@PMODULES_VERSION@:${PMODULES_VERSION}:g;"
	sed_cmd+="s:@MODULES_VERSION@:${MODULES_VERSION}:g;"
	sed_cmd+="s:@PMODULES_DISTFILESDIR@:${PMODULES_DISTFILESDIR}:g;"
	sed_cmd+="s:@PMODULES_TMPDIR@:${PMODULES_TMPDIR}:g;"
	sed_cmd+="s:@TCLSHDIR@:${PMODULES_HOME}/sbin:g;"
	sed_cmd+="s:@pager@::g;"
	sed_cmd+="s:@pageropts@::g;"
	sed_cmd+="s:@etcdir@:/opt/psi/config:g;"
	sed_cmd+="s:@VERSIONING@:#:g;"
	sed_cmd+="s:@prefix@:${PMODULES_HOME}:g;"
	sed_cmd+="s:@initdir@:${PMODULES_HOME}/init:g;"
	sed_cmd+="s:@MODULES_RELEASE@:${PMODULES_VERSION}:g;"
	
	sed "${sed_cmd}" "${SRC_DIR}/modulecmd.bash.in"   > "${SRC_DIR}/modulecmd.bash"
	sed "${sed_cmd}" "${SRC_DIR}/modulecmd.tcl.in"    > "${SRC_DIR}/modulecmd.tcl"
	sed "${sed_cmd}" "${SRC_DIR}/modmanage.bash.in"   > "${SRC_DIR}/modmanage.bash"
	sed "${sed_cmd}" "${SRC_DIR}/profile.bash.in"     > "${SRC_DIR}/profile.bash"
	sed "${sed_cmd}" "${SRC_DIR}/profile.csh.in"      > "${SRC_DIR}/profile.csh"
	sed "${sed_cmd}" "${SRC_DIR}/profile.zsh.in"      > "${SRC_DIR}/profile.zsh"

	install -d -m 0755 "${PMODULES_HOME}/bin"
	install -d -m 0755 "${PMODULES_HOME}/config"
	install -d -m 0755 "${PMODULES_HOME}/init"
	install -d -m 0755 "${PMODULES_HOME}/lib"
	install -d -m 0755 "${PMODULES_HOME}/libexec"
	install -d -m 0755 "${PMODULES_HOME}/sbin"

	install -m 0755 "${SRC_DIR}/modulecmd"		"${PMODULES_HOME}/bin"
	install -m 0755 "${SRC_DIR}/modulecmd.bash"	"${PMODULES_HOME}/libexec"
	install -m 0755 "${SRC_DIR}/modulecmd.tcl"	"${PMODULES_HOME}/libexec"
	install -m 0755 "${SRC_DIR}/modmanage"		"${PMODULES_HOME}/bin"
	install -m 0755 "${SRC_DIR}/modmanage.bash"	"${PMODULES_HOME}/libexec"
	install -m 0755 "${SRC_DIR}/modbuild"		"${PMODULES_HOME}/bin"

	install -m 0755 "${SRC_DIR}/profile.bash"	"${PMODULES_HOME}/config/profile.bash.sample"
	install -m 0755 "${SRC_DIR}/profile.csh"	"${PMODULES_HOME}/config/profile.csh.sample"
	install -m 0755 "${SRC_DIR}/profile.zsh"	"${PMODULES_HOME}/config/profile.zsh.sample"

	test -e "${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}" || mkdir -p "$_"

	test -e "${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/profile.bash" || \
		install -m 0755 "${SRC_DIR}/profile.bash"	"$_"

	test -e "${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/profile.csh" || \
		install -m 0755 "${SRC_DIR}/profile.csh"	"$_"

	test -e "${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/profile.zsh" || \
		install -m 0755 "${SRC_DIR}/profile.zsh"	"$_"

	test -e "${PMODULES_ROOT}/${PMODULES_CONFIG_DIR}/modbuild.conf" || \
		install -m 0755 "${config_file}" "$_"

	mkdir -p "${PMODULES_ROOT}/Tools/modulefiles"
	mkdir -p "${PMODULES_ROOT}/Libraries/modulefiles"
	test -e "${PMODULES_DISTFILESDIR}" || mkdir -p "$_"

	install -m 0644 "${SRC_DIR}/bash"		"${PMODULES_HOME}/init"
	install -m 0644 "${SRC_DIR}/bash_completion"	"${PMODULES_HOME}/init"
	install -m 0644 "${SRC_DIR}/csh"		"${PMODULES_HOME}/init"
	install -m 0644 "${SRC_DIR}/zsh"		"${PMODULES_HOME}/init"

	install -m 0644 "${SRC_DIR}/libpmodules.bash"	"${PMODULES_HOME}/lib"
	install -m 0644 "${SRC_DIR}/libpbuild.bash"	"${PMODULES_HOME}/lib"
	install -m 0644 "${SRC_DIR}/libstd.bash"	"${PMODULES_HOME}/lib"
	install -m 0755 -d				"${PMODULES_HOME}/lib/Pmodules"
	install -m 0644 "${SRC_DIR}/libmodules.tcl"	"${PMODULES_HOME}/lib/Pmodules"

	{
		cd "${PMODULES_HOME}/lib/Pmodules"
		"${BOOTSTRAP_DIR}/mkindex.tcl"
	}
}

#=============================================================================
#

declare -a build_opts=()
build_opts+=( '--bootstrap' )

declare subcmd=''
declare -a subcmd_args=()

while (( $# > 0 )); do
	case "$1" in
		--help | -h | -\? )
			usage
			;;
		--debug )
			set -x
			;;
		-* )
			std::die 1 "$1: illegal option"
			;;
		configure | compile | install )
			subcmd="$1"
			shift 1
			subcmd_args=( "$@" )
			shift $#
			;;
		* )
			std::die 1 "$1: Unknown sub-command."
			;;
	esac
	shift 1
done

[[ -n "${subcmd}" ]] || std::die 1 "Missing sub-command.\n\nUse 'build --help' to get some help..."


pmodules::${subcmd} "${subcmd_args[@]}"

