#!/bin/bash

#####################################################################
#                                                                   #
#          SmartKeyboard App Generator for iOS and Android          #
#               (c) Romain Michon CCRMA and Grame, 2016             #
#                                                                   #
#####################################################################

. faustpath

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

# exit if a command fails
set -e

# global option variables
ANDROID="0"
IOS="0"
NVOICES="12"
POLY2="0"
MIDI="0"
OSC=""
EFFECT=""
SOURCE=0
REUSE=0
INSTALL=0

echoHelp ()
{
	echo "FAUST2SMARTKEYB - MUSICAL MOBILE APP GENERATOR"
	echo ""
	echo "faust2smartkeyb takes a Faust code as its main argument and convert it into a ready-to-use app for Android or iOS. The only two required arguments of faust2smartkeyb are a Faust file and the target platform (-android or -ios):"
	echo ""
	echo "faust2smartkeyb -ios mySynth.dsp"
	echo "or"
	echo "faust2smartkeyb -android mySynth.dsp"
	echo ""
	echo "OPTIONS:"
	echo ""
	echo "-android: generate an Android app"
	echo "-ios: generate an iOS app"
	echo "-debug: activate debug mode"
	echo "-effect: allow to specify an effect Faust file (e.g., -effect myEffect.dsp)"
	echo "-help: dispay this help page"
	echo "-install: install the app on the connected device (Android only)"
	echo "-nvoices: specify the max number of voices"
	echo "-reuse: reuse the same project source"
	echo "-source: only generate the source (no compilation)"
	echo "-osc: adds OSC support to the app"
	echo ""
	echo "More information and tutorials at: https://ccrma.stanford.edu/~rmichon/smartKeyboard"
}

###########################
# Processing Arguments
###########################

while [ $1 ]
do
	p=$1

    if [ $p = "-help" ] || [ $p = "-h" ]; then
		echoHelp
		exit 0
    elif [[ -f "$p" ]]; then
		FILE="$p"
    elif [ $p = "-android" ]; then
		ANDROID=1
    elif [ $p = "-ios" ]; then
		IOS="1"
	elif [ $p = "-reuse" ]; then
		REUSE=1
	elif [ $p = "-source" ]; then
		SOURCE=1
	elif [ $p = "-debug" ]; then
		LOG="/dev/stdout"
	elif [ $p = "-install" ]; then
		INSTALL=1
	elif [ $p = "-osc" ]; then
		OSC="-osc"
    elif [ "$p" = "-effect" ]; then
        POLY2="1"
		shift
		if [[ -f "$1" ]]; then
			EFFECT=$1
		elif [ $1 = "auto" ]; then
			EFFECT=$1
		else
			echo "No file specified after -effect"
			echoHelp
			exit 1
		fi
    elif [ $p = "-nvoices" ]; then
		shift
		NVOICES=$1
    elif [ ${p:0:1} = "-" ]; then
        OPTIONS="$OPTIONS $p"
    elif [[ -f "$p" ]]; then
        FILES="$FILES $p"
    else
        OPTIONS="$OPTIONS $p"
    fi

shift

done

# Options post processing
#if [ -z "$OSC" ]; then
#	echo "No osc"
#	OSC=""
#fi

if [ -z $FILE ]; then
    echo "Please, provide a Faust file to process"
    exit 1
fi

###################################
# Configuring
###################################

APPNAME=$(basename "$FILE")
APPNAME="${APPNAME%.dsp}"
APPNAME=`filename2ident "$APPNAME"`
BUILDDIR="faustsmartkeyb.$APPNAME"

# making sure that platform is set and generate corresponding global vars
if [ $ANDROID -eq 1 ]; then
	APPFOLDER="$BUILDDIR/app/src/main"
elif [ $IOS -eq 1 ]; then
	APPFOLDER="$BUILDDIR/Faust"
else
	echo "Please, specify a platform: -android or -ios"
	echoHelp
	exit 1
fi

###############################
# Creating Default Project
###############################
PLATFORM=$(uname)

if [ $REUSE -eq 0 ] || [ ! -d "$BUILDDIR" ]; then
	if [ -d "$BUILDDIR" ]; then # if BUILDIR exists, then delete it
		echo "Delete existing app project $BUILDDIR" > $LOG
		rm -rf "$BUILDDIR"
	fi

	# copying new template app if no reuse
	if [ ! -d "$BUILDDIR" ]; then
		mkdir -p "$BUILDDIR"
		cp -r $FAUSTARCH/smartKeyboard/LICENCE.md "$BUILDDIR"
		if [ $ANDROID -eq 1 ]; then
			echo "Creating a new Android project in $BUILDDIR" > $LOG
			cp -r $FAUSTARCH/smartKeyboard/android/* "$BUILDDIR"

			# change 'faust' with real *APPNAME

			if [ $PLATFORM = "Darwin" ]; then
				sed -i '' 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $BUILDDIR/app/build.gradle
				sed -i '' 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $APPFOLDER/java/com/ccrma/faust/*
				sed -i '' 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $APPFOLDER/AndroidManifest.xml
				sed -i '' 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $APPFOLDER/res/layout/activity_main.xml
				sed -i '' 's,Faust,'$APPNAME',g' $APPFOLDER/res/values/strings.xml
				if [[ $OSC == "-osc" ]]; then
					sed -i '' 's,OSCCTRL=false,OSCCTRL=true,g' $BUILDDIR/app/build.gradle
					sed -i '' 's,set(OSCCTRL\ false),set(OSCCTRL\ true),g' $BUILDDIR/app/CMakeLists.txt
				fi
			else
				sed -i 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $BUILDDIR/app/build.gradle
				sed -i 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $APPFOLDER/java/com/ccrma/faust/*
				sed -i 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $APPFOLDER/AndroidManifest.xml
				sed -i 's,com.ccrma.faust,com.ccrma.'$APPNAME',g' $APPFOLDER/res/layout/activity_main.xml
				sed -i 's,Faust,'$APPNAME',g' $APPFOLDER/res/values/strings.xml
				if [[ $OSC == "-osc" ]]; then
					sed -i 's,OSCCTRL=false,OSCCTRL=true,g' $BUILDDIR/app/build.gradle
					sed -i 's,set(OSCCTRL\ false),set(OSCCTRL\ true),g' $BUILDDIR/app/CMakeLists.txt
				fi
			fi
			mv $APPFOLDER/java/com/ccrma/faust $APPFOLDER/java/com/ccrma/$APPNAME
		elif [ $IOS -eq 1 ]; then
			echo "Creating a new iOS project in $BUILDDIR" > $LOG
			cp -r $FAUSTARCH/smartKeyboard/iOS/* "$BUILDDIR"
			if [ $PLATFORM = "Darwin" ]; then
				sed -i '' 's,$(TARGET_NAME),'$APPNAME',g' $BUILDDIR/Faust.xcodeproj/project.pbxproj
				sed -i '' 's,ccrma.Faust,ccrma.'$APPNAME',g' $BUILDDIR/Faust.xcodeproj/project.pbxproj
			else
				sed -i 's,$(TARGET_NAME),'$APPNAME',g' $BUILDDIR/Faust.xcodeproj/project.pbxproj
				sed -i 's,ccrma.Faust,ccrma.'$APPNAME',g' $BUILDDIR/Faust.xcodeproj/project.pbxproj
			fi
            # Put OSC in project in all cases, even if not compiled
            # cp -r $FAUSTARCH/osclib "$BUILDDIR"/Faust
        fi
	fi
fi

###########################
# Adding DSP
###########################

if [ $ANDROID -eq 1 ]; then
	if [ -z "$EFFECT" ]; then # no effect
		echo "Adding DSP with no effect chain to the app" > $LOG
		faust2api -android $OSC -nvoices "$NVOICES" -nodoc $OPTIONS "$FILE" > $LOG
	else
		echo "Adding DSP with effect chain to the app" > $LOG
		faust2api -android $OSC -nvoices "$NVOICES" -effect "$EFFECT" -nodoc $OPTIONS "$FILE" > $LOG
	fi
	unzip "dsp-faust.zip" > $LOG
	mv "dsp-faust" "$BUILDDIR"
	rm "dsp-faust.zip"
	cp -r "$BUILDDIR/dsp-faust/cpp" "$APPFOLDER"
	cp $BUILDDIR/dsp-faust/java/* "$APPFOLDER/java/com/DspFaust"
	rm -r "$BUILDDIR/dsp-faust"
elif [ $IOS -eq 1 ]; then
	if [ -z "$EFFECT" ]; then # no effect
		echo "Adding DSP with no effect chain to the app" > $LOG
		faust2api -ios $OSC -midi -nvoices "$NVOICES" -nodoc $OPTIONS "$FILE" > $LOG
	else
		echo "Adding DSP with effect chain to the app" > $LOG
		faust2api -ios $OSC -midi -nvoices "$NVOICES" -effect "$EFFECT" -nodoc $OPTIONS "$FILE" > $LOG
	fi
	unzip "dsp-faust.zip" > $LOG
	mv "dsp-faust" "$BUILDDIR"
	rm "dsp-faust.zip"
	cp $BUILDDIR/dsp-faust/* "$APPFOLDER"
	rm -r "$BUILDDIR/dsp-faust"
fi

###########################
# Compilation
###########################

if [ $SOURCE -eq 0 ]; then
	if [ $ANDROID -eq 1 ]; then
		echo "Starting Android compilation" > $LOG
		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.6/bin/gradle ]; then
			FAUSTGRADLE=${FAUSTGRADLE:=/opt/gradle/gradle-4.6/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 > $LOG
		echo "An Android app \"$APPNAME.apk\" was created in the current folder"
	elif [ $IOS -eq 1 ]; then
		echo "Starting iOS compilation" > $LOG
		(
			xcodebuild -project "$BUILDDIR/Faust.xcodeproj" -target Faust PRODUCT_NAME=$APPNAME
			cd "$BUILDDIR" && xcodebuild -scheme Faust PRODUCT_NAME=$APPNAME
		)  > $LOG || exit 1
		rm -rf "$APPNAME.app"
    	mv "$BUILDDIR/build/Release-iphoneos/$APPNAME.app" .
		echo "An iOS app \"$APPNAME.app\" was created in the current folder"
	fi
fi

###########################
# Installation
###########################

if [ $INSTALL -eq 1 ]; then
	if [ $ANDROID -eq 1 ]; then
		echo "Installing the app" > $LOG
		adb install -r $APPNAME.apk
	elif [ $ANDROID -eq 1 ]; then
		echo "Automatic installation is only possible on Android"
	fi
fi

###########################
# Cleaning
###########################

if [ $REUSE -eq 0 ] && [ $SOURCE -eq 0 ]; then
	echo "Delete app project $BUILDDIR" > $LOG
	rm -rf $BUILDDIR
else
	echo "An app project $BUILDDIR was created or updated in the current directory"
fi
