#!/bin/bash

progname=$(basename $0)

usage() {
	cat >&2 <<EOF
Usage: $progname [options] <outdir> <depends>...

options:
  -a, --copy-all         copy all files in module tree (not just sources
		         required for build)
  -b, --build-type=TYPE  generate build infrastructure of TYPE
                         (one of 'make', 'make+config', 'automake', 'waf')
EOF
}

# parse options, setting the following flags
build_type=

opts=$(getopt -o ab: --long copy-all,build-type: -n $progname -- "$@")

if [ $? != 0 ]
then
	usage
	exit 1
fi

eval set -- "$opts"
MODFILES_ARGS="--no-tests --no-other"

while :
do
	case "$1" in
		-a|--copy-all)
			MODFILES_ARGS=""
			shift
			;;
		-b|--build-type)
			build_type="$2"
			shift 2
			;;
		--)
			shift
			break
			;;
		*)
			echo "Internal error!">&2
			exit 1
			;;
	esac
done

# we need at least two non-option arguments: outdir and a list of ccan
# modules
if [ $# -lt 2 ]
then
	usage
	exit 1
fi

# check --build-type argument sanity
case "$build_type" in
	''|'make'|'make+config'|'automake'|'waf')
		;;
	*)
		echo "Invalid build type '$build_type'" >&2
		exit 1
esac

srcdir=$(dirname $0)/../
outdir="$1"
shift
modules="$@"

if [ -e "$outdir" ]
then
	echo "Output directory '$outdir' already exists" >&2
	exit 1
fi

tmpdir="$(mktemp -d)"
# sanity check, we don't want to be overwriting stuff in arbitrary dirs
[ $? -eq 0 -a -d "${tmpdir}" ] || exit 1

# We'll need the ccan_depends tool, but also a clean source tree. Build
# tools/ccan_depends, and store it in $tmpdir for later use

echo "Building ccan_depends, modfiles"
ccan_depends="$tmpdir/ccan_depends"
modfiles="$tmpdir/modfiles"
make -s -C "$srcdir" tools/ccan_depends tools/modfiles
[ $? -eq 0 ] || exit 1
cp "$srcdir/tools/ccan_depends" "$ccan_depends"
cp "$srcdir/tools/modfiles" "$modfiles"

echo "Cleaning source tree"
make -s -C "$srcdir" clean
[ $? -eq 0 ] || exit 1

# clean up on error
trap 'rm -rf $tmpdir' EXIT

copy_ccan_module() {
	module_dir="$1"
	module_srcdir="$srcdir/$module_dir"
	module_destdir="$tmpdir/$module_dir"

	mkdir -p "$module_destdir"
	# Copy license
	license="$module_srcdir/LICENSE"
	[ -e "$license" ] && cp -a "$license" "$module_destdir"
	for f in $("$modfiles" $MODULES_ARGS --no-license --git-only "$module_dir"); do
	    mkdir -p $(dirname "$module_destdir"/"$f")
	    cp "$module_srcdir"/$f "$module_destdir"/$f
	done
}

# generate list of directories to copy
for module in $modules
do
	# ccan_depends takes a directory name
	module_dir="$srcdir/ccan/$module"

	# we need the module itself...
	echo "ccan/$module"

	# .. plus dependencies
	"$ccan_depends" "$module_dir"

	if [ $? -ne 0 ]
	then
		echo "Invalid ccan module '$module'?" >&2
		exit 1
	fi
done |
sort -u |
while read dir
do
	echo "Adding $dir"
	copy_ccan_module $dir
done

# we're done with the dependency-tracking, remove the tool from our
# temporary directory
rm "$ccan_depends" "$modfiles"

echo "Adding licenses"
license_dir="$tmpdir/licenses"
mkdir "$license_dir"

find "$tmpdir" -type l -name LICENSE |
while read license
do
	license_link=$(readlink "$license")
	licence_file=$(basename "$license_link")
	license_src="$srcdir/licenses/$licence_file"
	license_dest="$license_dir/$license_file"
	cp "$license_src" "$license_dest"
done

echo "Adding build infrastructure"

# generate automake Makefile.am
automakefile="$tmpdir/Makefile.am"
if [ "$build_type" = "automake" ]
then
	(
		echo "noinst_LIBRARIES = libccan.a"
		echo "libccan_a_SOURCES = \\"
		cd "$tmpdir"
		find ccan -maxdepth 2 -name '*.[ch]' |
			sed -e 's,^,\t,;$!s,$, \\,'
	) > "$automakefile"
fi

makefile="$tmpdir/Makefile"
if [ "$build_type" = "make" -o "$build_type" = "make+config" ]
then
	# add ccan Makefile
	cp "$srcdir/Makefile-ccan" "$tmpdir/"

	# add top-level Makefile
	cat > "$makefile" << EOF
all: libccan.a

include Makefile-ccan
EOF
fi

# optionally add configurator, and relevant parts to top-level Makefile
if [ "$build_type" = "make+config" ]
then
	echo "Adding configurator"
	mkdir -p "$tmpdir/tools/configurator"
	cp -a "$srcdir/tools/configurator" "$tmpdir/tools/"

	cat >> "$makefile" <<EOF
tools/configurator/configurator: tools/configurator/configurator.c

config.h: tools/configurator/configurator Makefile Makefile-ccan
	tools/configurator/configurator \$(CC) \$(CCAN_CFLAGS) > \$@ \\
		|| rm -f \$@

objs = \$(patsubst %.c, %.o, \$(wildcard ccan/*/*.c))
\$(objs): config.h

EOF
fi

if [ "$build_type" = "waf" ]
then
	echo "Adding waf wscript"
	cat > "$tmpdir/wscript" << EOF
def build(ctx):
    ctx(features     = 'c cstlib',
        source       = ctx.path.ant_glob('**/*.c'),
        target       = 'ccan',
        includes     = '.')
EOF
fi

mv "$tmpdir" "$outdir"
echo "Done. ccan source tree built in $outdir"

trap - EXIT
