#!/bin/bash

BIN_NAME=$(basename $0)
BIN_DIR=$(dirname $(realpath $0))

BASE_PATH=$(realpath $(dirname $0))

DEBUG=0
QUIET=0
VERBOSE=0

VERSION_INFO=();
BUILD_NUMBER=1
PKG_COMP="testing"
PKG_COMP_OVERWRITE=0
PKG_COMP_CLEAN=0

SRC_DIR=$(realpath $(pwd))

UpdateBuildDir ()
{
	BUILD_DIR=$1
	DST_TOOL_DIR="${BUILD_DIR}/.${BIN_NAME}"
	[[ -d ${DST_TOOL_DIR} ]] || mkdir -p ${DST_TOOL_DIR}
	if [[ ! -d ${DST_TOOL_DIR} ]]; then
		echo -e "Invalid build directory!" 1>&2
		exit 3
	fi
	BUILD_DIR=$(realpath ${BUILD_DIR})
	CPACK_OPT_FILE="${BUILD_DIR}/CPackOptions.cmake"
	DST_TOOL_DIR="${BUILD_DIR}/.${BIN_NAME}"
	[[ -e "${DST_TOOL_DIR}/source" ]] && SRC_DIR=$(cat "${DST_TOOL_DIR}/source")
	SRC_TOOL_DIR="${SRC_DIR}/.${BIN_NAME}"
	[[ -d ${SRC_TOOL_DIR} ]] || mkdir -p ${SRC_TOOL_DIR}
	if [[ ! -d ${SRC_TOOL_DIR} ]]; then
		echo -e "Invalid source directory!" 1>&2
		exit 3
	fi
	VERSION_FILE="${SRC_TOOL_DIR}/version"
	REVISION_FILE="${SRC_TOOL_DIR}/revision"
}

UpdateBuildDir $(pwd)

UpdateSrcDir ()
{
	SRC_DIR=$(realpath $1)
	echo "${SRC_DIR}" > "${DST_TOOL_DIR}/source" 
	UpdateBuildDir "${BUILD_DIR}"
}

Usage ()
{
	local msg=$1
	if [[ -n ${msg} ]]; then
		echo -e "\n${msg}" 1>&2
	fi
	echo -e "\nusage: ${BIN_NAME} [-b <version>][-B <build-dir>][-C <pkg-comp>][-d][-h][-o][-p <file>][-s][-S <src-dir>][-t <target>][-v][-V <version> [<file>]]" 1>&2
	echo -e "\t-b <version>\tGenerate release tag: <version>-<build+1> (Deprecated)" 1>&2
	echo -e "\t-B <build-dir>\tDefine build directory (Default: '${BUILD_DIR}')" 1>&2
	echo -e "\t-C <pkg-comp>\tDefine package component (Default: '${PKG_COMP}')" 1>&2
	echo -e "\t-d\t\tEnable debug mode" 1>&2
	echo -e "\t-h\t\tThis help output" 1>&2
	echo -e "\t-o\t\tCreate CPACK option file (Obsolete)" 1>&2
	echo -e "\t-p <file>\tPatch control file (Version...)" 1>&2
	echo -e "\t-q\t\tQuite mode" 1>&2
	echo -e "\t-s\t\tSetup build environment (Obsolete)" 1>&2
	echo -e "\t-S\t\tDefine source directory (Default: '${SRC_DIR}')" 1>&2
	echo -e "\t-t <target>\tDefine build target -> build sub-directory" 1>&2
	echo -e "\t-v\t\tVerbose (multi)" 1>&2
	echo -e "\t-V <version>\tUpdate version tag (Deprecated)" 1>&2
	echo -e "\nusage: ${BIN_NAME} [-B <build-dir>][-C <pkg-comp>][-d][-h][-q][-S <src-dir>][-t <target>][-v] <cmd> [<sub-cmd>] [<arg>] [<opt>]\n" 1>&2
	echo -e "\t<cmd>\t<sub-cmd>\t<arg/opts>" 1>&2
	echo -e "\tbuild\tpackage\t\t[-i][-I]\t\tBuild package" 1>&2
	echo -e "\t\t\t\t-i\t\t\tInstall package option" 1>&2
	echo -e "\t\t\t\t-I\t\t\tClean install package option" 1>&2
	echo -e "\tbuild\t[program]\t\t\t\tBuild program" 1>&2
	echo -e "\tcreate\tversion-header\t<version> <file>\tCreate version header file" 1>&2
	echo -e "\tcreate\tcpack-option\t\t\t\tCreate CPACK option file" 1>&2
	echo -e "\tcreate\tmanifest\t<pkg> [--key=val]\tCreate PKG manifest" 1>&2
	echo -e "\tget\tversion\t\t\t\t\tGet full version string (<major>.<minor>.<patch>[+<tweak>][-<debian-release>])" 1>&2
	echo -e "\tget\tversion\t\t[--main-version]\tGet main version (<major>.<minor>)" 1>&2
	echo -e "\tget\tversion\t\t[--major-version]\tGet major informaion (<major>)" 1>&2
	echo -e "\tget\tversion\t\t[--minor-version]\tGet minor informaion (<minor>)" 1>&2
	echo -e "\tget\tversion\t\t[--build-version]\tGet build informaion (<patch>[+<tweak>])" 1>&2
	echo -e "\tget\tversion\t\t[--patch-version]\tGet build informaion (<patch>)" 1>&2
	echo -e "\tget\tversion\t\t[--tweak-version]\tGet build informaion (<tweak>)" 1>&2
	echo -e "\tget\tversion\t\t[--debian-release]\tGet debian-release (<empty> => CPACK_DEBIAN_PACKAGE_RELEASE)" 1>&2
	echo -e "\tget\tversion\t\t[--upstream-version]\tGet upstream-version (=> CPACK_PACKAGE_VERSION)" 1>&2
	echo -e "\tget\tversion\t\t[--debian-version]\tGet full debian package version string (=> CPACK_DEBIAN_FILE_NAME)" 1>&2
	echo -e "\tinstall\t\t\t[-I][<pkg>]\t\tInstall package <pkg> or default from build directory" 1>&2
	echo -e "\t\t\t\t-I\t\t\tClean install package option" 1>&2
	echo -e "\tpatch\t\t\t<file>\t\t\tPatch control file <file>" 1>&2
	echo -e "\tset\tversion\t\t<version> [-u <file>]\tSet and update version tag" 1>&2
	echo -e "\t\t\t\t-u <file>\t\tCreate version header file\n" 1>&2
	[[ -z ${msg} ]] || exit 1
	exit 0
}

ErrorMsgAndExit ()
{
	local msg=$1
	echo -e "${msg}" 1>&2
	exit 2
}

VerifySourceDir ()
{
	[[ -e ${SRC_DIR}/CMakeLists.txt ]] && return 0
	return -1
}

LoadVersionInfo ()
{
	local TMP_VERSION_FILE="${SRC_VERSION_FILE}"
	[[ -e ${TMP_VERSION_FILE} ]] || TMP_VERSION_FILE="${DST_TOOL_DIR}/version" 
	[[ -e ${TMP_VERSION_FILE} ]] || ErrorMsgAndExit "Version file <${TMP_VERSION_FILE}> not found!"
	local VERSION=$(cat ${TMP_VERSION_FILE})
	SetupVersionInfo ${VERSION}
}

SetupVersionInfo ()
{
	local VERSION=$1
	#
	#	split <version> -> <upstream>-<debian> 
	#
	local UPSTREAM=${VERSION%-*}
	local DEBIAN=${VERSION/$UPSTREAM/}
	DEBIAN=${DEBIAN##*-}
	if [[ -z ${DEBIAN} ]]; then
		local MAIN=${UPSTREAM%.*}
		local BUILD=${UPSTREAM/$MAIN/}
		BUILD=${BUILD##*.}
		local MAJOR=${MAIN%.*}
		local MINOR=${MAIN/$MAJOR/}
		MINOR=${MINOR##*.}
	else
		local MAIN=${UPSTREAM}
		local MAJOR=${MAIN%%.*}
		local MINOR=${MAIN/$MAJOR/}
		MINOR=${MINOR##*.}
		local PREFIX=${DEBIAN%.*}
		local BUILD=${DEBIAN/$PREFIX/}
		BUILD=${BUILD##*.}
		[[ -z ${BUILD} ]] && BUILD=${PREFIX}
	fi
	local PATCH=${BUILD%+*}
	local TWEAK=${BUILD/$PATCH/}
	TWEAK=${TWEAK##*+}
	VERSION_INFO=("${VERSION}" "${MAIN}" "${MAJOR}" "${MINOR}" "${BUILD}" "${PATCH}" "${TWEAK}" "${DEBIAN}" "${UPSTREAM}" "${VERSION}")
	[[ ${VERBOSE} -gt 0 ]] && echo "VERSION_INFO: ${VERSION_INFO[@]}"
}

#
#   V1.0 Commands
#

GenerateReleaseTag ()
{
#
#	FixMe: need to cope with RO source dir => no direct SRC_VERSION_FILE access allowed !!!
#	
	local vTag=$1
	[[ ${QUIET} -gt 0 ]] || echo "Generate release tag (${vTag})..." 1>&2
	if [ ! -e ${REVISION_FILE} ]; then
		if [ -e ${VERSION_FILE} ]; then
			cat ${VERSION_FILE} > ${REVISION_FILE}
		fi
	fi
	if [ -e ${REVISION_FILE} ]; then
		CURRENT=$(cat ${REVISION_FILE})
		VERSION=${CURRENT%-*}
		BUILD=${CURRENT##*-}
		if [ "${vTag}" == "${VERSION}" ]; then
			BUILD_NUMBER=$((${BUILD} + 1))
		fi
	fi
	echo "${vTag}-${BUILD_NUMBER}" > ${REVISION_FILE} 
	echo "${BUILD_NUMBER}"
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

Create_CPACK_OptionFile ()
{
	[[ ${QUIET} -gt 0 ]] || echo "Create_CPACK_OptionFile ()..." 1>&2
  
#	EXEC_PROGRAM($(realpath $0) ARGS -b ${CPACK_PACKAGE_VERSION} OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_RELEASE)
#	SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}-${CPACK_DEBIAN_PACKAGE_RELEASE}")
#	STRING(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME)
#	EXEC_PROGRAM(dpkg ARGS --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
#	#DEBIAN_FILE_NAME#<PackageName>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
#	SET(CPACK_DEBIAN_FILE_NAME "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
#	EXEC_PROGRAM($(realpath $0) ARGS -p ${CPACK_PACKAGE_DIRECTORY}/resources/DEBIAN/postinst OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_DUMMY)
  
	cat > ${CPACK_OPT_FILE} <<-EndOfMessage
		EXEC_PROGRAM($(realpath $0) ARGS -q get version --upstream-version OUTPUT_VARIABLE CPACK_PACKAGE_VERSION)
#		EXEC_PROGRAM($(realpath $0) ARGS -q get version --debian-release OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_RELEASE)
		SET(CPACK_DEBIAN_PACKAGE_RELEASE)
		EXEC_PROGRAM($(realpath $0) ARGS -q get version --debian-version OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_VERSION)
		STRING(TOLOWER "\${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME)
		EXEC_PROGRAM(dpkg ARGS --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
		#DEBIAN_FILE_NAME#<PackageName>_<VersionNumber>-<DebianRevisionNumber>_<DebianArchitecture>.deb
#		SET(CPACK_DEBIAN_FILE_NAME "\${CPACK_DEBIAN_PACKAGE_NAME}_\${CPACK_PACKAGE_VERSION}-\${CPACK_DEBIAN_PACKAGE_RELEASE}_\${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
		SET(CPACK_DEBIAN_FILE_NAME "\${CPACK_DEBIAN_PACKAGE_NAME}_\${CPACK_DEBIAN_PACKAGE_VERSION}_\${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb")
		EXEC_PROGRAM($(realpath $0) ARGS -q create manifest \${CPACK_DEBIAN_FILE_NAME} --NAME=\${CPACK_DEBIAN_PACKAGE_NAME} --VERSION=\${CPACK_DEBIAN_PACKAGE_VERSION} --ARCH=\${CPACK_DEBIAN_PACKAGE_ARCHITECTURE} OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_DUMMY)
#		EXEC_PROGRAM($(realpath $0) ARGS -q create manifest \${CPACK_DEBIAN_PACKAGE_NAME}_\${CPACK_PACKAGE_VERSION}_\${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb --NAME=\${CPACK_DEBIAN_PACKAGE_NAME} --VERSION=\${CPACK_PACKAGE_VERSION} --ARCH=\${CPACK_DEBIAN_PACKAGE_ARCHITECTURE} OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_DUMMY)
 		EXEC_PROGRAM($(realpath $0) ARGS -q patch \${CPACK_PACKAGE_DIRECTORY}/resources/DEBIAN/postinst OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_DUMMY)
	EndOfMessage
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

InstallPackage ()
{
	local PKG_FILE=$1
	[[ ${QUIET} -gt 0 ]] || echo "Install package (${PKG_FILE})..." 1>&2
	if [[ -z ${PKG_FILE} ]]; then
		[[ -e ${DST_TOOL_DIR}/PKG ]] || ErrorMsgAndExit "No packet definition found!"
		PKG_FILE="${BUILD_DIR}/$(cat ${DST_TOOL_DIR}/PKG)"
	fi
	[[ ${VERBOSE} -gt 0 ]] && echo -e "PKG_FILE: ${PKG_FILE}"
	[[ -e ${PKG_FILE} ]] || ErrorMsgAndExit "Packet not found!"
	#
	# below this point BUILD_DIR and DST_TOOL_DIR might be invalid => use MANIFEST instead
	#
	LoadVersionInfo
	local sVersion=${VERSION_INFO[0]}
	local MANIFEST="$(dirname ${PKG_FILE})/.${BIN_NAME}"
	[[ -e ${MANIFEST}/VERSION ]] || ErrorMsgAndExit "Manifest not found!"
	local pVersion=$(cat ${MANIFEST}/VERSION)
	[[ ${pVersion} == ${sVersion} ]] || ErrorMsgAndExit "Build version mismatch!"
	local NAME=$(cat ${MANIFEST}/NAME)
	local ARCH=$(cat ${MANIFEST}/ARCH)
	local DIST=$(cat ${MANIFEST}/DIST)
	local CODE=$(cat ${MANIFEST}/CODE)
	local COMP=$(cat ${MANIFEST}/COMP)
	[[ ${PKG_COMP_OVERWRITE} -gt 0 ]] && COMP=${PKG_COMP} 
	#
	# schnipp => move below to 'update-apt-archive'
	#
	local PKG_PATH="/opt/share/dpkg/${DIST}/pool/${CODE}/${COMP}"
	[[ ${VERBOSE} -gt 0 ]] && echo -e "PKG_PATH: ${PKG_PATH}"
	mkdir -p ${PKG_PATH}
	[[ ${PKG_COMP_CLEAN} -gt 0 ]] && rm ${PKG_PATH}/${NAME}_*_${ARCH}.deb
	cp -p ${PKG_FILE} ${PKG_PATH}
	#
	# schnapp
	#
	update-apt-archive
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

PatchControlFile ()
{
	local FILE=$1
	[[ ${QUIET} -gt 0 ]] || echo "Patch control file (${FILE})..." 1>&2
	LoadVersionInfo
	sed -i -r "s/^PKG_VERSION=\"[0-9]+(\.[0-9]+)+.*\"/PKG_VERSION=\"${VERSION_INFO[0]}\"/" ${FILE}	
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

SetupBuildEnvironment ()
{
	[[ ${QUIET} -gt 0 ]] || echo "Setup build environment..." 1>&2
	sudo apt-get install lsb-release
	sudo apt-get install cmake
	sudo apt-get install libboost-all-dev
	sudo apt-get install libmysqlcppconn-dev
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

#
#   V2.0 Commands
#

DoBuild ()
{
	local MAKE_TARGET=${1#program}
	local INSTALL_OPT=$2
	[[ ${QUIET} -gt 0 ]] || echo "Build($1)..." 1>&2
	VerifySourceDir || ErrorMsgAndExit "Invalid source path <${SRC_DIR}>!"
	[[ ${SRC_DIR} = ${BUILD_DIR} ]] && UpdateBuildDir ${SRC_DIR}/build/local
	echo -e "SRC_DIR:\t$SRC_DIR"
	echo -e "BUILD_DIR:\t$BUILD_DIR"
	local BUILD_TARGET=${BUILD_DIR#${SRC_DIR}/build/}
	echo -e "BUILD_TARGET:\t$BUILD_TARGET" 
	[ -e ${BUILD_TARGET} ] && ErrorMsgAndExit "Invalid target <${BUILD_TARGET}>!"
	#
	# Update version information now, since source path might be read-only during build process !!!
	#
	#	FixMe: need to cope with RO source dir => no direct SRC_VERSION_FILE access allowed !!!
	#
	if [ -e ${VERSION_FILE} ]; then
		[[ -x ${BIN_DIR}/build-id ]] && ${BIN_DIR}/build-id -f ${VERSION_FILE} -p ${SRC_DIR}
	else
		[ -d ${SRC_DIR}/build/local ] || mkdir -p ${SRC_DIR}/build/local
		pushd ${SRC_DIR}/build/local > /dev/null
		cmake ${SRC_DIR}
		[ $? -eq 0 ] || ErrorMsgAndExit "Cannot create version information (cmake)!"
		make version
		[ $? -eq 0 ] || ErrorMsgAndExit "Cannot create version information (make version)!"
		popd > /dev/null
	fi
	#
	# Start build process
	#
	pushd ${BUILD_DIR} > /dev/null
	if [[ $BUILD_TARGET = "local" ]]; then
		cmake ${SRC_DIR}
		if [ $? -eq 0 ]; then
			make ${MAKE_TARGET}
		fi
	else
    	#
    	# TODO: add 'clean' option to clear build directory
    	#
    	sudo rm -rf ${BUILD_DIR}/*
    	docker run -it -v ${BUILD_DIR}:/target -v ${SRC_DIR}:/target/source:ro docker.ac.pestinger.net:5000/rcc-build-env:${BUILD_TARGET} /bin/bash /target/source/.${BIN_NAME}/build.sh
    	[[ -z ${INSTALL_OPT} ]] || InstallPackage
  	fi
	popd > /dev/null
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

CreateManifest ()
{
	local PKG=$1
	declare -a OPTS=("${!2}")
	[[ ${QUIET} -gt 0 ]] || echo "CreateManifest ($PKG, ${OPTS[@]})..." 1>&2
	echo "${PKG}" > "${DST_TOOL_DIR}/PKG"
	echo "${PKG_COMP}" > "${DST_TOOL_DIR}/COMP"
	for opt in ${OPTS[@]}; do
  		local key=${opt%=*}
		local val=${opt/${key}/}
  		val=${val##*=}
  		[[ ${VERBOSE} -gt 0 ]] && echo -e "KEY: ${key^^}\tVAL: ${val}"
    	echo "${val}" > "${DST_TOOL_DIR}/${key^^}"
	done
	local DIST=$(lsb_release -si)
	echo "${DIST,,}" > "${DST_TOOL_DIR}/DIST"
	local CODE=$(lsb_release -sc)
	echo "${CODE,,}" > "${DST_TOOL_DIR}/CODE"
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

CreateVersionHeaderFile ()
{
	local VERSION=$1
	local FILE=$2
	[[ ${QUIET} -gt 0 ]] || echo "CreateVersionHeaderFile ('${VERSION}', '${FILE}')..." 1>&2
	SetupVersionInfo ${VERSION}
	if [[ ${VERBOSE} -gt 0 ]]; then
		echo "=================="
		echo "MAIN:  ${VERSION_INFO[1]}"
		echo "BUILD: ${VERSION_INFO[4]}"
		echo "------------------"
		echo "MAJOR: ${VERSION_INFO[2]}"
		echo "MINOR: ${VERSION_INFO[3]}"
		echo "PATCH: ${VERSION_INFO[5]}"
		echo "TWEAK: ${VERSION_INFO[6]}"
		echo "=================="
	fi
	echo "#ifndef _PROJECT_VERSION_H" >${FILE}
	echo "#define _PROJECT_VERSION_H" >>${FILE}
	echo "" >>${FILE}
	echo "#define PROJECT_VERSION_MAJOR ${VERSION_INFO[2]}" >>${FILE}
	echo "#define PROJECT_VERSION_MINOR ${VERSION_INFO[3]}" >>${FILE}
	echo "#define PROJECT_VERSION_PATCH ${VERSION_INFO[5]}" >>${FILE}
	echo "#define PROJECT_VERSION_TWEAK ${VERSION_INFO[6]}" >>${FILE}
	echo "" >>${FILE}
	echo "#endif" >>${FILE}
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

GetVersion ()
{
	local arg=$1
	[[ ${QUIET} -gt 0 ]] || echo "GetVersion (${arg})..." 1>&2
	LoadVersionInfo
	case ${arg} in
		main)
			[[ -z ${VERSION_INFO[1]} ]] || echo "${VERSION_INFO[1]}"
			;;
		major)
			[[ -z ${VERSION_INFO[2]} ]] || echo "${VERSION_INFO[2]}"
			;;
		minor)
			[[ -z ${VERSION_INFO[3]} ]] || echo "${VERSION_INFO[3]}"
			;;
		build)
			[[ -z ${VERSION_INFO[4]} ]] || echo "${VERSION_INFO[4]}"
			;;
		patch)
			[[ -z ${VERSION_INFO[5]} ]] || echo "${VERSION_INFO[5]}"
			;;
		tweak)
			[[ -z ${VERSION_INFO[6]} ]] || echo "${VERSION_INFO[6]}"
			;;
		release)
			[[ -z ${VERSION_INFO[7]} ]] || echo "${VERSION_INFO[7]}"
			;;
		upstream)
			[[ -z ${VERSION_INFO[8]} ]] || echo "${VERSION_INFO[8]}"
			;;
		version)
			[[ -z ${VERSION_INFO[9]} ]] || echo "${VERSION_INFO[9]}"
			;;
		*)
			echo "${VERSION_INFO[0]}"
			;;
	esac
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

SetVersion ()
{
	local REQ=$1
	local H_FILE=$2
	[[ ${QUIET} -gt 0 ]] || echo "SetVersion ('${REQ}', '${H_FILE}')..." 1>&2
	local OLD=${REQ}
	local CUR=${REQ}
	#
	#	In case of possible RO file system, do calculation in DST section
	#
	local DST_VERSION_FILE="${DST_TOOL_DIR}/version"
	if [[ -e ${VERSION_FILE} ]]; then
		cp -p ${VERSION_FILE} ${DST_VERSION_FILE}
		OLD=$(cat ${VERSION_FILE})
		[[ ${QUIET} -gt 0 ]] || echo "Old Version: ${OLD}" 1>&2
		local REV=${REQ%.*}
		[[ ${QUIET} -gt 0 ]] || echo "Revision: ${REV}" 1>&2
		if dpkg --compare-versions "${OLD}" lt "${REV}"; then
			echo "${REQ}" > ${DST_VERSION_FILE}
			CUR=${REQ}
		else
			CUR=${OLD}
		fi
	else
		echo "${REQ}" > ${DST_VERSION_FILE}
	fi 
	[[ ${QUIET} -gt 0 ]] || echo "Current Version: ${CUR}" 1>&2
	[[ -x ${BIN_DIR}/build-id ]] && ${BIN_DIR}/build-id -f ${DST_VERSION_FILE} -p ${SRC_DIR}
	local NEW=$(cat ${DST_VERSION_FILE})
	[[ ${QUIET} -gt 0 ]] || echo "New Version: ${NEW}" 1>&2
	if [[ ${OLD} != ${NEW} ]]; then
		[[ ${QUIET} -gt 0 ]] || echo "Update version file!" 1>&2
		[[ -w ${VERSION_FILE} ]] || ErrorMsgAndExit "Version file is read-only!"
		cat ${DST_VERSION_FILE} > ${VERSION_FILE} 
	fi
	if [[ ! -z ${H_FILE} ]]; then
		if [[ -e ${H_FILE} ]]; then
			if [[ ${H_FILE} -ot ${VERSION_FILE} ]]; then
				CreateVersionHeaderFile ${NEW} ${H_FILE}
			fi
		else
			CreateVersionHeaderFile ${NEW} ${H_FILE}
		fi
	fi	
	[[ ${QUIET} -gt 0 ]] || echo "done." 1>&2
}

#
#   Start main processing
#
CMD=
SUBCMD=
CMDARG=
CMDARG2=
CMDOPT=()
#
#	Global options first
#
while getopts ":b:B:C:dhop:qsS:t:vV:-:" opt; do
	case "${opt}" in
		b)
			[ -z "${CMD}" ] || Usage
			CMD=${opt}
			CMDARG=${OPTARG}
			QUIET=1 # need to be silent
			;;
		B)
			UpdateBuildDir ${OPTARG}
			;;
		C)
			PKG_COMP=${OPTARG}
			PKG_COMP_OVERWRITE=1
			;;
		d)
			DEBUG=1
			VERBOSE=$((${VERBOSE} +1))
			;;
		h)
			Usage
			;;
		o)
			[ -z "${CMD}" ] || Usage
			[[ ${QUIET} -gt 0 ]] || echo "Warning: Obsolete option used <${opt}>!" 1>&2
			CMD="create"
			SUBCMD="cpack-option"
			;;
		p)
			[ -z "${CMD}" ] || Usage
			CMD="patch"
			CMDARG=${OPTARG}
			;;
		q)
			QUIET=1
			;;
		s)
			[ -z "${CMD}" ] || Usage
			CMD=${opt}
			;;
		S)
			UpdateSrcDir ${OPTARG} 
			;;
		t)
			UpdateBuildDir ${SRC_DIR}/build/${OPTARG}
			;;
		v)
			VERBOSE=$((${VERBOSE} +1))
			;;
		V)
			[ -z "${CMD}" ] || Usage
#			[[ ${QUIET} -gt 0 ]] || echo "Warning: Obsolete option used <${opt}>!" 1>&2
			CMD="set"
			SUBCMD="version"
			CMDARG=${OPTARG}
			CMDARG2=${!OPTIND}
			;;
		\?)
      			Usage "Non-option argument (#1): '-${OPTARG}'"
			;;
		*)
			if [ "${OPTERR}" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
				Usage "Non-option argument (#2): '-${opt}'"
			fi
			;;
	esac
done
shift $((OPTIND -1))
[[ -z ${CMD} ]] && [[ $# -gt 0 ]] && CMD=${1,,}; shift
[[ -z ${CMD} ]] && Usage "<cmd> option expected!"

[[ ${VERBOSE} -gt 0 ]] && echo -e "\nCMD: ${CMD}\tSUB: ${SUBCMD}\tARG: ${CMDARG}\tOPT: ${CMDOPT[@]}\tPARAM: $1\n" 1>&2

if [[ ${DEBUG} -gt 0 ]]; then
	echo -e "BIN-DIR:\t${BIN_DIR}" 1>&2
	echo -e "SRC-DIR:\t${SRC_DIR}" 1>&2
	echo -e "BUILD-DIR:\t${BUILD_DIR}\n" 1>&2
	exit 0
fi 

case "${CMD}" in
	b)
		GenerateReleaseTag ${CMDARG}
		;;
	s)
		SetupBuildEnvironment
		;;
	build)
		[[ -z ${SUBCMD} ]] && [[ $# -eq 0 ]] && SUBCMD="program"
		[[ -z ${SUBCMD} ]] && [[ $# -gt 0 ]] && SUBCMD=${1,,}; shift
		case "${SUBCMD}" in
			pa*)
				OPTIND=1
				while getopts ":iI" opt; do
					case "${opt}" in
						i)
							CMDARG="install"
							PKG_COMP_CLEAN=0
							;;
						I)
							CMDARG="install"
							PKG_COMP_CLEAN=1
							;;
						\?)
							Usage "Invalid command option '${OPTARG}'"
							;;
						*)
      						Usage "Invalid 'build package' <option>: '${opt}\t${OPTARG}'"
      						;;
					esac
				done        
				shift $((OPTIND -1))
				DoBuild package ${CMDARG}
		    	;;
			pr*)
				DoBuild program
		    	;;
			*)
				Usage "Invalid 'build' <sub-cmd>: '${SUBCMD}'"
				;;
		esac
		;;  
	create)
		[[ -z ${SUBCMD} ]] && [[ $# -gt 0 ]] && SUBCMD=${1,,}; shift
		[[ -z ${SUBCMD} ]] && Usage "'create' <sub-cmd> expected!"
		case "${SUBCMD}" in
			cpack-o*)
				Create_CPACK_OptionFile
				;; 
			manifest)
				[[ -z ${CMDARG} ]] && [[ $# -gt 0 ]] && CMDARG=${1}; shift
				[[ -z ${CMDARG} ]] && Usage "<pkg> argument expected!"
				OPTIND=1
				while getopts ":-:" opt; do
					case "${opt}" in
						-)
							CMDOPT+=(${OPTARG})
							;;
						\?)
							Usage "Invalid command option '${OPTARG}'"
							;;
						*)
							ErrorMsgAndExit "OOPS: ${opt}\t${OPTARG}"
					esac
				done
				shift $((OPTIND -1))
				CreateManifest ${CMDARG} CMDOPT[@]
				;;
			version-h*)
				[[ -z ${CMDARG} ]] && [[ $# -gt 0 ]] && CMDARG=${1}; shift
				[[ -z ${CMDARG} ]] && Usage "<version> argument expected!"
				[[ -z ${CMDARG2} ]] && [[ $# -gt 0 ]] && CMDARG2=${1}; shift
				[[ -z ${CMDARG2} ]] && Usage "<file> argument expected!"
				CreateVersionHeaderFile ${CMDARG} ${CMDARG2}
				;;
			*)
				Usage "Invalid 'create' <sub-cmd>: '${SUBCMD}'"
				;;
		esac
		;;  
	get)
		[[ -z ${SUBCMD} ]] && [[ $# -gt 0 ]] && SUBCMD=${1,,}; shift
		[[ -z ${SUBCMD} ]] && Usage "'get' <sub-cmd> expected!"
		case "${SUBCMD}" in
			version)
				OPTIND=1
				while getopts ":-:" opt; do
					case "${opt}" in
						-)
							case "${OPTARG}" in
								main*)
									CMDARG="main"
									;;
								major*)
									CMDARG="major"
									;;
								minor*)
									CMDARG="minor"
									;;
								build*)
									CMDARG="build"
									;;
								patch*)
									CMDARG="patch"
									;;
								tweak*)
									CMDARG="tweak"
									;;
								debian-r*)
									CMDARG="release"
									;;
								upstream*)
									CMDARG="upstream"
									;;
								debian-v*)
									CMDARG="version"
									;;
								*)
									Usage "Invalid command option '${OPTARG}'"
									;;
							esac
							;;
						\?)
							Usage "Invalid command option '${OPTARG}'"
							;;
						*)
							ErrorMsgAndExit "OOPS: ${opt}\t${OPTARG}"
					esac
				done
				shift $((OPTIND -1))
				GetVersion ${CMDARG}
				;;
			*)
				Usage "Invalid 'get' <sub-cmd>: '${SUBCMD}'"
				;;
		esac
		;;
	install)
		OPTIND=1
		while getopts ":I" opt; do
			case "${opt}" in
				I)
					PKG_COMP_CLEAN=1              
					;;
				\?)
					Usage "Invalid command option '${OPTARG}'"
					;;
				*)
	   				Usage "Invalid 'install' <option>: '${opt}\t${OPTARG}'"
      				;;
			esac
		done        
		shift $((OPTIND -1))
		[[ -z ${CMDARG} ]] && [[ $# -gt 0 ]] && CMDARG=${1}; shift
		InstallPackage ${CMDARG}
		;;
	patch)
		[[ -z ${CMDARG} ]] && [[ $# -gt 0 ]] && CMDARG=${1}; shift
		[[ -z ${CMDARG} ]] && Usage "<file> argument expected!"
		PatchControlFile ${CMDARG}
		;;	
	set)
		[[ -z ${SUBCMD} ]] && [[ $# -gt 0 ]] && SUBCMD=${1,,}; shift
		[[ -z ${SUBCMD} ]] && Usage
		case "${SUBCMD}" in
			version)
				[[ -z ${CMDARG} ]] && [[ $# -gt 0 ]] && CMDARG=${1}; shift
				[[ -z ${CMDARG} ]] && Usage
				OPTIND=1
				while getopts ":u:" opt; do
					case "${opt}" in
						u)
							CMDARG2=${OPTARG}              
							;;
						\?)
							Usage "Invalid command option '${OPTARG}'"
							;;
						*)
      				Usage "Invalid 'set version' <option>: '${opt}\t${OPTARG}'"
      				;;
					esac
				done        
				shift $((OPTIND -1))
				SetVersion ${CMDARG} ${CMDARG2}
				;;
			*)
				Usage "Invalid 'set' <sub-cmd>: '${SUBCMD}'"
				;;
		esac
		;;
	*)
		Usage "Unknown <cmd>: '${CMD}'"
		;;
esac
exit 0

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
