#! /bin/bash -e

#####################################################################
#                                                                   #
#               Compile a Faust program to an Android app           #
#               (c) Romain Michon CCRMA and Grame, 2014             #
#               (c) Yann Orlarey Grame, 2015                        #
#                                                                   #
#####################################################################

. faustpath
. faustoptflags
. usage.sh

# change if you want to get the log of what's happening
LOG="/dev/null"

# exit if a command fails
set -e

# Global variables for file and options
FILE=
INSTALL=0
SOURCE=0
SWIG=0
FAUST=0
KEYBOARD=0
REUSE=0
SOUNDFILE=0
OSCCTRL=0

echoHelp() 
{
    usage faust2android "[options] [Faust options] <file.dsp>"
    platform Android
    require Android SDK
    echo "Compile a Faust program to an Android app"
    option
    option -osc
    option -source "creates an eclipse project of the app in the current directory."
    option -swig "regenerates the C++ and the JAVA interface for the native portion of the app."
    option -faust "only carries out the Faust compilation and install the generated C++ file in the JNI folder."
    option -reuse "preserves build directory and reuse it to speedup compilation."
    option -soundfile
    option -install "once compilation is over, installs the generated apk on the Android device connected to the computer"
    option -debug "activates verbose output"
    option "Faust options"
    exit
}

if [ "$#" -eq 0 ]; then
    echo 'Please, provide a Faust file to process !'
    echo ''
    echoHelp
fi

# PHASE 2 : dispatch command arguments
for p in $@; do
	if [ $p = "-swig" ]; then
		SWIG=1
	elif [[ -f "$p" ]] && [ ${p: -4} == ".dsp" ]; then
		FILE="$p"
	elif [ $p = "-install" ]; then
		INSTALL=1
	elif [ $p = "-soundfile" ]; then
		SOUNDFILE="1"
	elif [ $p = "-osc" ]; then
		OSCCTRL="1"
	elif [ $p = "-source" ]; then
		SOURCE=1
	elif [ $p = "-faust" ]; then
		FAUST=1
	elif [ $p = "-reuse" ]; then
		REUSE=1
	elif [ $p = "-keyboard" ]; then
		KEYBOARD=1
	elif [ $p = "-debug" ]; then
		LOG="/dev/stdout"
	elif [ "$p" = "-noagc" ]; then
		NOAGC="1"
	elif [ $p = "-help" ] || [ $p = "-h" ]; then
		echoHelp
	elif [ ${p:0:1} = "-" ]; then
		OPTIONS="$OPTIONS $p"
	else
		OPTIONS="$OPTIONS $p"
	fi
done

# only carry out the faust compilation
if [ $FAUST -eq 1 ]; then
	faust $OPTIONS -i -a api/DspFaust.cpp "$FILE" -o "app/src/main/cpp/DspFaust.cpp"
	exit 1
fi

# Create the temporary directory where compilation will take place

APPNAME=$(basename "$FILE")
APPNAME="${APPNAME%.dsp}"
APPNAME=`filename2ident "$APPNAME"`
BUILDDIR="faustandro.$APPNAME"
APPFOLDER="$BUILDDIR/app/src/main"
JNIFOLDER="$APPFOLDER/cpp"

if [ $REUSE -eq 0 ]; then
	if [ -d "$BUILDDIR" ]; then
		echo "Delete existing Android project $BUILDDIR" > $LOG
		rm -rf "$BUILDDIR"
	fi
fi

if [ ! -d "$BUILDDIR" ]; then
	echo "Creating new Android project $BUILDDIR"  > $LOG

	mkdir -p "$BUILDDIR"
	cp -r $FAUSTARCH/android/*  "$BUILDDIR"
	install -d $JNIFOLDER
	# Copy include files *.h if any (ignore any error here)
	(cp *.h $JNIFOLDER 2> $LOG) || true

	# change 'faust' with real *APPNAME
	PLATFORM=$(uname)

	if [ $PLATFORM = "Darwin" ]; then
		sed -i '' 's,com.faust,com.'$APPNAME',g' $BUILDDIR/app/build.gradle
	if [ "$NOAGC" = "1" ]; then
		sed -i '' 's,-DDISABLE_AGC,'-DDISABLE_AGC',g' $BUILDDIR/app/build.gradle
	else
		sed -i '' 's,-DDISABLE_AGC,'',g' $BUILDDIR/app/build.gradle
	fi
		sed -i '' 's,com.faust,com.'$APPNAME',g' $APPFOLDER/java/com/faust/*
		sed -i '' 's,com.faust,com.'$APPNAME',g' $APPFOLDER/java/com/triggertrap/seekarc/*
		sed -i '' 's,com.faust,com.'$APPNAME',g' $APPFOLDER/AndroidManifest.xml
		sed -i '' 's,com.faust,com.'$APPNAME',g' $APPFOLDER/res/layout/*
		sed -i '' 's,1,'$APPNAME',g' $APPFOLDER/res/values/strings.xml
	else
		sed -i 's,com.faust,com.'$APPNAME',g' $BUILDDIR/app/build.gradle
	if [ "$NOAGC" = "1" ]; then
		sed -i 's,-DDISABLE_AGC,'-DDISABLE_AGC',g' $BUILDDIR/app/build.gradle
	else
		sed -i 's,-DDISABLE_AGC,'',g' $BUILDDIR/app/build.gradle
	fi
		sed -i 's,com.faust,com.'$APPNAME',g' $APPFOLDER/java/com/faust/*
		sed -i 's,com.faust,com.'$APPNAME',g' $APPFOLDER/java/com/triggertrap/seekarc/*
		sed -i 's,com.faust,com.'$APPNAME',g' $APPFOLDER/AndroidManifest.xml
		sed -i 's,com.faust,com.'$APPNAME',g' $APPFOLDER/res/layout/*
		sed -i 's,1,'$APPNAME',g' $APPFOLDER/res/values/strings.xml
	fi

	mv $APPFOLDER/java/com/faust $APPFOLDER/java/com/$APPNAME

	# TODO wrong: should be checked
	if [ $SWIG -eq 1 ]; then
		rm -rf $APPFOLDER/java/com/dsp_faust || true
		mkdir -p $APPFOLDER/java/com/dsp_faust
		swig -java -package com.dsp_faust -includeall -verbose -outdir $APPFOLDER/java/com/dsp_faust -c++ -I$FAUSTINC -I/System/Library/Frameworks/JavaVM.framework/Headers -I$JNIFOLDER -o $JNIFOLDER/java_interface_wrap.cpp $BUILDDIR/dsp_faust_interface.i
	fi
else
	echo "Reusing existing Android project $BUILDDIR" > $LOG
fi

# Copying the Faust API files in the project
cp $FAUSTARCH/api/DspFaust.h $JNIFOLDER
cp $FAUSTARCH/api/android/jni/java_interface_wrap.cpp $JNIFOLDER
mkdir $APPFOLDER/java/com/DspFaust
cp $FAUSTARCH/api/android/jni/*.java $APPFOLDER/java/com/DspFaust

# Compile the Faust code for the NDK
faust $OPTIONS -i -json -a api/DspFaust.cpp "$FILE" -o "$JNIFOLDER/DspFaust.cpp" || exit

# Add soundfile support if needed
if [ $SOUNDFILE -eq 1 ]; then
	cat $FILE.json | awk '
                        BEGIN { FS=":"; SOFI=0; }
                                /"soundfile"/ { SOFI=1; }
                                /"url"/ {
                                if (SOFI) {
                                        match($2, /"[^"]*/);
                                        split(substr($2, RSTART+2, RLENGTH-3), res, ";");
                                        for (x in res) print substr(res[x], 2, length(res[x])-2);
                                        SOFI=0;
                                }
                        }
                        ' > $APPNAME-tmp.txt
	for snd in $(cat $APPNAME-tmp.txt); do
			if [ -f $snd ]; then
					if [ ${snd:0:1} = "/" ]; then
							echo "Warning: soundfile with absolute path is not copied !"
					else
							#create destination path and possibly create directory
							sfpath="$APPFOLDER/assets/$(dirname $snd)/"
							if ! [ -d $sfpath ]; then
									echo "Create $sfpath"
									mkdir -p $sfpath
							fi
							echo "Copy $snd in apk"
							cp $snd $sfpath
					fi
			else
					echo "Error: file $snd not found !"
			fi
	done
	if [ $PLATFORM = "Darwin" ]; then
		sed -i '' 's,__CURRENT_ANDROID_PACKAGE__,com.'$APPNAME',g' $APPFOLDER/cpp/DspFaust.cpp
	else
		sed -i 's,__CURRENT_ANDROID_PACKAGE__,com.'$APPNAME',g' $APPFOLDER/cpp/DspFaust.cpp
	fi
	mv $BUILDDIR/app/CMakeLists_sndfile.txt $BUILDDIR/app/CMakeLists.txt
	if [ $OSCCTRL -eq 1 ]; then
	if [ $PLATFORM = "Darwin" ]; then
		sed -i '' 's,set(OSCCTRL\ false),set(OSCCTRL\ true),g' $BUILDDIR/app/CMakeLists.txt
	else
		sed -i 's,set(OSCCTRL\ false),set(OSCCTRL\ true),g' $BUILDDIR/app/CMakeLists.txt
	fi
  fi
	rm $APPNAME-tmp.txt
else
	rm $BUILDDIR/app/CMakeLists_sndfile.txt
	if [ $OSCCTRL -eq 1 ]; then
	if [ $PLATFORM = "Darwin" ]; then
		sed -i '' 's,set(OSCCTRL\ false),set(OSCCTRL\ true),g' $BUILDDIR/app/CMakeLists.txt
	else
		sed -i 's,set(OSCCTRL\ false),set(OSCCTRL\ true),g' $BUILDDIR/app/CMakeLists.txt
	fi
  fi
	rm -r $BUILDDIR/app/lib # that's soooo dirty but that will do for now...
fi
rm $FILE.json

# Run Gradle
cd $BUILDDIR

# Try to use installed gradle instead of local ./gradlew in order
# to avoid potential problems when compiling in a shared folder
# where execution rights may not be granted (i.e. on a google VM)
# In order to install gradle-4.6:
#	wget https://services.gradle.org/distributions/gradle-4.6-bin.zip
#   unzip -d /opt/gradle gradle-4.6-bin.zip

if [ -f /opt/gradle/gradle-4.10.1/bin/gradle ]; then
	FAUSTGRADLE=${FAUSTGRADLE:=/opt/gradle/gradle-4.10.1/bin/gradle}
else
	FAUSTGRADLE=${FAUSTGRADLE:=./gradlew}
	chmod a+x ./gradlew
fi

echo "USED GRADLE=$FAUSTGRADLE" > $LOG

$FAUSTGRADLE assembleRelease > $LOG
cd ..

cp -r $BUILDDIR/app/build/outputs/apk/release/app-release.apk $APPNAME.apk

# ****************
# TREAT OPTIONS
# ****************

if [ $INSTALL -eq 1 ]; then
	adb install -r $APPNAME.apk
fi

if [ $SOURCE -eq 1 ]; then
	rm -rf faustApp
	mv $BUILDDIR faustApp
	echo "An Android studio project named faustApp was created." > $LOG
else
	if [ $REUSE -eq 0 ]; then
		echo "Delete Android project $BUILDDIR" > $LOG
		rm -rf $BUILDDIR
	fi
fi

echo "$APPNAME.apk;"
