#!/bin/bash

NAME=$(basename $0)
MONO_API_INFO="mono-api-info"
MONO_API_DIFF="mono /usr/lib/mono/4.5/mono-api-diff.exe"

KEEP=0
if [ "$1" = "-k" ]; then
	KEEP=1
	KEEP_PARAM="-k"
	shift
fi

ABI=
if [ "$1" = "-a" ]; then
	ABI=1
	ABI_PARAM="-a"
	MONO_API_INFO_PARAMS=--abi
	shift
fi

if [ $# -lt 2 ]; then
	echo "usage: $NAME [-k] [-a] old.dll|deb|changes new.dll|deb|changes"
	exit 1
fi

if [ ! -r $1 ]; then
	echo "Error: $1 does not exist or is not readable"
	exit 1
fi

if [ ! -r $2 ]; then
	echo "Error: $2 does not exist or is not readable"
	exit 1
fi

if ! [ "$1" = "${1%.deb}" ]; then
	DEB_TMP_DIR1=/tmp/$NAME-$$-$RANDOM
	DEB_TMP_DIR2=/tmp/$NAME-$$-$RANDOM

	mkdir $DEB_TMP_DIR1
	if [ $? != 0 ]; then
		echo "Error: could not create: $DEB_TMP_DIR1"
		exit 1
	fi

	mkdir $DEB_TMP_DIR2
	if [ $? != 0 ]; then
		echo "Error: could not create: $DEB_TMP_DIR2"
		exit 1
	fi

	dpkg -x $1 $DEB_TMP_DIR1
	if [ $? != 0 ]; then
		echo "Error: could extract: $1"
		exit 1
	fi

	dpkg -x $2 $DEB_TMP_DIR2
	if [ $? != 0 ]; then
		echo "Error: could extract: $2"
		exit 1
	fi

	DLLS=$(find $DEB_TMP_DIR1 -type f -name "*.dll")
	for DLL1 in $DLLS; do
		FILE=${DLL1#$DEB_TMP_DIR1/}
		DLL2=$DEB_TMP_DIR2/$FILE
		#echo $DLL1
		#echo $DLL2

		echo -e "Library:\t\t/$FILE"
		$0 $RUNTIME_VERSION_PARAM $KEEP_PARAM $ABI_PARAM $DLL1 $DLL2
		echo
	done

	rm -rf $DEB_TMP_DIR1
	rm -rf $DEB_TMP_DIR2
	
	exit 0
fi

if ! [ "$1" = "${1%.changes}" ]; then
	DEB_DIR1=$(dirname $1)
	DEB_DIR2=$(dirname $2)
	DEBS=$(grep ".deb$" $2 | cut -d ' ' -f 6)
	for DEB in $DEBS; do
		PKG_VERSION2=$(dpkg -I $DEB_DIR2/$DEB | grep Version: | cut -d ':' -f 2 | sed -e 's/^ *//')
		break
	done

	DEBS=$(grep ".deb$" $1 | cut -d ' ' -f 6)
	for DEB1 in $DEBS; do
		PKG_NAME=$(dpkg -I $DEB_DIR1/$DEB1  | grep Package: | cut -d ':' -f 2 | sed -e 's/^ *//')
		PKG_ARCH=$(dpkg -I $DEB_DIR1/$DEB1  | grep Architecture: | cut -d ':' -f 2 | sed -e 's/^ *//')
		DEB2=$DEB_DIR2/${PKG_NAME}_${PKG_VERSION2}_${PKG_ARCH}.deb

		echo -e "Package:\t\t$PKG_NAME"
		echo    "------------------------------------------------------"
		$0 $RUNTIME_VERSION_PARAM $KEEP_PARAM $ABI_PARAM $DEB1 $DEB2
		echo
	done

	exit 0
fi

ASM_NAME=$(basename $1)
API_OLD=$(tempfile --suffix=_$ASM_NAME.api-old)
API_NEW=$(tempfile --suffix=_$ASM_NAME.api-new)
API_DIFF=$(tempfile --suffix=_$ASM_NAME.api-diff)

${MONO_API_INFO} $MONO_API_INFO_PARAMS "$1" > ${API_OLD} 2> /dev/null
if [ $? != 0 ]; then
	echo "Error: ${MONO_API_INFO} on $1 failed!"
	exit 1
fi
${MONO_API_INFO} $MONO_API_INFO_PARAMS "$2" > ${API_NEW} 2> /dev/null
if [ $? != 0 ]; then
	echo "Error: ${MONO_API_INFO} on $2 failed!"
	exit 1
fi
${MONO_API_DIFF} ${API_OLD} ${API_NEW} > ${API_DIFF} 2> /dev/null
if [ $? != 0 ]; then
	echo "Error: ${MONO_API_DIFF} failed!"
	exit 1
fi

version_changed=0
grep -q 'Assembly version not equal: ' ${API_DIFF}
if [ $? = 0 ]; then
	version_changed=1
fi

name=$(head -n3 ${API_DIFF} | tail -n1 | sed 's;\ ;\n;g' | grep ^name | cut -d\= -f2 | sed 's;\";;g')
missing_total=$(head -n3 ${API_DIFF} | tail -n1 | sed 's;\ ;\n;g' | grep ^missing_total | cut -d\= -f2 | sed 's;\";;g')
extra_total=$(head -n3 ${API_DIFF} | tail -n1 | sed 's;\ ;\n;g' | grep ^extra_total | cut -d\= -f2 | sed 's;\";;g')

if [ -z $missing_total ]; then
	missing_total=0
fi
if [ -z $extra_total ]; then
	extra_total=0
fi

echo "CLI API Check"
echo -e "Assembly Name:\t\t$name"
echo -e "Missing Interfaces:\t$missing_total"
echo -e "Additional Interfaces:\t$extra_total"

if [ $missing_total ]
then
	if [ $missing_total -gt 0 ]
	then
		echo 
		echo "The two assemblies you compared are NOT API compatible!"
		echo "You must use a new package name!"
	fi
fi

if [ $extra_total ]
then
	if [ $extra_total -gt 0 ]
	then
		echo
		echo "The new assembly has additional interfaces. You must raise"
		echo "the minimal version in clilibs!"
	fi
fi

if [ $version_changed = 1 ]; then
	echo
	echo "The assembly versions do NOT MATCH!"
	echo "If they are API compatible you MUST generate and install a GAC policy file!"
fi

rm -f ${API_OLD} ${API_NEW}
if [ $KEEP = 1 ]; then
	echo "API diff file: ${API_DIFF}"
else
	rm -f ${API_OLD} ${API_NEW}
fi