#!/bin/bash

pushd $(dirname "$0") > /dev/null
D=$(pwd -P)
popd > /dev/null

ME="$0"
BUNDLE_NAME="Gedit"
BUNDLE="$D/$BUNDLE_NAME.app"

function do_strip {
	tp=$(file -b --mime-type "$1")

	if [ "$tp" != "application/octet-stream" ]; then
		return
	fi

	name=$(mktemp -t bundle)
	st=$(stat -f %p "$1")

	strip -o "$name" -S "$1"
	mv -f "$name" "$1"

	chmod "$st" "$1"
	chmod u+w "$1"
}

function dmg_help_short() {
	echo "Create a dmg from a bundle"
}

function cmd_dmg() {
	# Copied and modified from Banshee
	if [ ! -d "$BUNDLE" ]; then
		cmd_make
	fi

	VOLUME_NAME="$BUNDLE_NAME"

	if [ ! -z "$1" ]; then
		DMG_FILE="$1.dmg"
	else
		DMG_FILE="$D/$BUNDLE_NAME.dmg"
	fi

	DMG_APP="$BUNDLE"
	TMP_MOUNT_POINT="$D/$VOLUME_NAME.mounted"
	FINAL_MOUNT_POINT="/Volumes/$VOLUME_NAME"

	rm -f $DMG_FILE
	rm -f $DMG_FILE.master

	# Compute an approximated image size in MB, and bloat by 30 MB
	image_size=$(du -ck "$DMG_APP" | tail -n1 | cut -f1)
	image_size=$((($image_size * 11) / 10000))

	echo "Creating disk image (${image_size}MB)..."

	TMPNAME="${DMG_FILE%.dmg}_tmp.dmg"

	cp "$D/data/template.dmg.bz2" "$TMPNAME.bz2"
	bunzip2 "$TMPNAME.bz2"

	hdiutil resize -size ${image_size}m "$TMPNAME" || exit 1

	echo "Attaching to disk image..."
	hdiutil attach "$TMPNAME" -readwrite -noautoopen -mountpoint "$TMP_MOUNT_POINT" -quiet || exit 1

	echo "Populating image..."
	rsync -az "$DMG_APP" "$TMP_MOUNT_POINT/" || exit 1

	echo "Ensuring permissions"
	chmod -Rf go-w "$TMP_MOUNT_POINT" 2>/dev/null

	echo "Blessing image..."
	bless --folder "$TMP_MOUNT_POINT" --openfolder "$TMP_MOUNT_POINT" || exit 1

	echo "Detaching from disk image..."
	hdiutil detach "$TMP_MOUNT_POINT" -quiet || exit 1

	echo "Converting to final image..."
	hdiutil convert -quiet -format UDBZ -o "$DMG_FILE" "$TMPNAME" || exit 1

	# Make internet-enable
	hdiutil internet-enable -yes "$DMG_FILE" || exit 1

	rm -f "$TMPNAME"

	n=$(basename "$DMG_FILE")
	echo "Done $n."
}

function make_help_usage() {
	echo "[-f]"
}

function make_help_short() {
	echo "Make the $BUNDLE_NAME.app bundle"
}

function build_gtk_mac_bundler() {
	b="$D/../build/build"
	lbin=$("$b" env local-bin)

	if [ -x "$lbin/gtk-mac-bundler" ]; then
		return
	fi

	echo "Installing gtk-mac-bundler..."

	home=$("$b" env home)
	sbin="$home/source"

	mkdir -p "$sbin"

	(
		cd "$sbin"

		if [ ! -d gtk-mac-bundler ]; then
			git clone https://github.com/jessevdk/gtk-mac-bundler || exit 1
		fi

		(
			cd gtk-mac-bundler
			git checkout -b stable 5994aa557ebb24687ed07e74910e4007521a53b4 || exit 1
			HOME="$home" make install
		) || exit 1
	) || exit 1
}

function make_fake_help_long() {
	echo "Create a fake bundle pointing towards files in the build. This is useful mostly to test bundle support."
}

function make_fake_help_short() {
	echo "Create a fake bundle"
}

function cmd_make_fake() {
	fake="$D/Gedit-fake.app"

	rm -rf "$fake"
	mkdir -p "$fake/Contents"

	b="$D/../build/build"
	inst=$("$b" env inst)
	source=$("$b" env source)

	mkdir -p "$fake/Contents/Resources"

	for d in share lib; do
		ln -s "$inst/$d" "$fake/Contents/Resources/$d"
	done

	mkdir "$fake/Contents/MacOS"

	bin="$fake/Contents/MacOS/Gedit"

	printf "#!/bin/bash\n\nexec $b run \"$source/gedit/gedit/gedit\"\n" > "$bin"
	chmod u+x "$bin"

	echo "APPL????" > "$fake/Contents/PkgInfo"

	cp "$D/data/Info.plist" "$fake/Contents/"
	cp "$D/data/gedit.icns" "$fake/Contents/Resources/"
}

function cmd_make() {
	build_gtk_mac_bundler

	if [ -d "$BUNDLE" ]; then
		rm -rf "$BUNDLE"
	fi

	b="$D/../build/build"

	# No idea why it's not writable, but we need it to be so that install_name_tool
	# can change the link paths
	inst=$("$b" env inst)
	chmod u+w "$inst/lib/libpython3.3m.dylib"

	lbin=$("$b" env local-bin)

	echo "Generating bundle from Gedit.bundle specification..."
	"$b" run "$lbin/gtk-mac-bundler" "$D/data/Gedit.bundle" || exit 1

	mv "$D/data/$BUNDLE_NAME.app" "$BUNDLE"

	echo "Removing unneeded files from bundle"

	# Remove pyc and pyo files
	for d in lib share/gedit/plugins; do
		find "$BUNDLE/Contents/Resources/$d/"* -type f -regex '.*\.py[oc]' -exec 'rm -f {}' 2>/dev/null
		find "$BUNDLE/Contents/Resources/$d/"* -type d -name '__pycache__' -exec 'rmdir {}' 2>/dev/null
	done

	echo "Creating localized names..."
	locales=$(find "$inst/share/locale" -name gedit.mo | sed 's/.*locale\/\([^\/]*\)\/.*/\1/g' | /usr/bin/grep -v @)

	for locale in en $locales; do
		printf "$locale "
		ldir="$BUNDLE/Contents/Resources/$locale.lproj"

		lname=$(LANG=$locale "$b" run gettext gedit "Text Editor")

		mkdir -p "$ldir"

		echo "CFBundleName = \"Gedit\";" > "$ldir/InfoPlist.strings"
		echo "CFBundleDisplayName = \"Gedit $lname\";" >> "$ldir/InfoPlist.strings"
	done

	printf ", done...\n\nDo you want to strip debug symbols? [\033[1myes\033[0m/no] "
	read strip

	if [ "$strip" = "yes" ] || [ -z "$strip" ]; then
		echo "Strip debug symbols from bundle binaries"

		# Strip debug symbols from libraries/modules
		for i in $(find -E "$BUNDLE/Contents/Resources" -type f -regex '.*\.(so|dylib)$' 2>/dev/null); do
			do_strip "$i"
		done

		# Strip debug symbols from binaries
		for i in $(find "$BUNDLE/Contents/Resources/bin" -type f 2>/dev/null); do
			if [ -x "$i" ]; then
				do_strip "$i"
			fi
		done

		# Strip debug symbols from main binary
		do_strip "$BUNDLE/Contents/MacOS/gedit-bin"
	fi
}

function help_help_short() {
	echo "Shows this help message"
}

function cmd_help() {
	if [ -z "$1" ]; then
		echo "Usage: $ME [command]"
		echo ""
		echo "Available commands:"
		echo ""

		for cmd in "${commands[@]}"; do
			printf "  \033[1m$cmd\x1B[0m "

			l=${#cmd}
			let d="$commandsmaxlen - $l + 1"

			printf "%${d}s" ""
			echo -n "- "

			icmd=${cmd/-/_}

			if [[ $(type -t "${icmd}_help_short") = "function" ]]; then
				"${icmd}_help_short"
			else
				echo ""
			fi
		done

		echo ""
	else
		cmd="cmd_${1/-/_}"

		if [[ $(type -t "$cmd") != "function" ]]; then
			printf "Invalid command \033[1m$1\033[0m, available commands are: $cmds\n"
			exit 1
		fi

		printf "Usage: $ME \033[1m$1\033[0m "

		if [[ $(type -t "${1/-/_}_help_usage") = "function" ]]; then
			"${1/-/_}_help_usage"
		else
			echo ""
		fi

		echo ""

		if [[ $(type -t "${1/-/_}_help_long") != "function" ]]; then
			"${1/-/_}_help_short"
		else
			"${1/-/_}_help_long"
		fi
	fi
}

commands=()
commandsmaxlen=0

while read line
do
	cmd=${line#declare -f }

	if [[ "$cmd" = cmd_* ]]; then
		cname=${cmd#cmd_}

		commands+=(${cname/_/-})

		l=${#cname}

		if [[ $l > $commandsmaxlen ]]; then
			commandsmaxlen=$l
		fi
	fi
done < <(declare -F)

cmds=$(printf ", \033[1m%s\033[0m" "${commands[@]}")
cmds=${cmds:2}

if [ -z "$1" ]; then
	cmd_help
	exit 0
fi

cmd="cmd_${1/-/_}"

if [[ $(type -t "$cmd") != "function" ]]; then
	printf "Invalid command $1, available commands are: $cmds\n"
	exit 1
fi

shift 1
"$cmd" "$@"
