#!/bin/bash -e

. faustpath

#FAUST DATA:
[ -z "$ARCHFILE" ] && ARCHFILE=$FAUSTARCH/bela.cpp
#BELA DATA:
[ -z "$BBB_ADDRESS" ] && BBB_ADDRESS="root@192.168.7.2"
[ -z "$BBB_BELA_HOME" ] && BBB_BELA_HOME="/root/Bela"
[ -z "$BBB_PROJECT_HOME" ] && BBB_PROJECT_HOME="${BBB_BELA_HOME}/projects/"
[ -z "$BELA_CPPFLAGS" ] && BELA_CPPFLAGS=""
[ -z "$BELA_LDLIBS" ] && BELA_LDLIBS=""

BELA_CPPFLAGS="$BELA_CPPFLAGS"

#variables:
NVOICES=0
POLY=""
EFFECT=""
MIDIDEFS=""
OSCDEFS=""
SEND2BELA=""
OPTIONS=""

#-------------------------------------------------------------------
#PHASE 1 : dispatch command arguments
#-------------------------------------------------------------------
while [ $1 ] 
do
    p=$1

    # HELP:
    if [ $p = "-help" ] || [ $p = "-h" ]; then
        echo "faust2bela [-midi] [-gui] [-nvoices <num>] [-effect <auto or file.dsp>] [-soundfile] [-osc] [-tobela] [additional Faust options (-vec -vs 8...)] <file.dsp>"
        echo "Use '-midi' to activate MIDI control"
        echo "Use '-gui' to activate a self-hosted GUI interface. This requires that you installed libmicrohttpd and libHTTPDFaust."
        echo "Use '-nvoices <num>' to produce a polyphonic self-contained DSP with <num> voices, it must need -midi option also"
        echo "Polyphonic mode means MIDI instrument with at least 1 voice, so include monophonic instrument. Use no arguments for a simple effect."
        echo "Use '-effect <effect.dsp>' to produce a polyphonic DSP connected to a global output effect, ready to be used with MIDI"
        echo "Use '-effect auto' to produce a polyphonic DSP connected to a global output effect defined as 'effect' in <file.dsp>, ready to be used with MIDI"
        echo "Use '-soundfile' when compiling DSP using 'soundfile' primitive, to add needed resources"
        echo "Use '-osc' to activate OSC control"
	    echo "Use '-tobela' to send C++ file into bela, and run it."
        exit
    fi

    # -NVOICES:
    if [ $p = "-nvoices" ]; then
        shift
        NVOICES=$1
    # -EFFECT:
    elif [ $p = "-effect" ]; then
        POLY="POLY2"
        shift
        EFFECT=$1
    # -MIDI
    elif [ $p = "-midi" ]; then
        MIDIDEFS="MIDI"
    elif [ $p = "-osc" ]; then
        OSCDEFS="OSC"
    elif [ $p = "-gui" ]; then
        GUIDEFS="GUI"
    elif [ $p = "-soundfile" ]; then
        SOUNDFILEDEFS="SOUNDFILE"
    elif [ $p = "-tobela" ]; then
        SEND2BELA="OK"
    else
        OPTIONS="$OPTIONS $p"        
    fi

shift

done
#-------------------------------------------------------------------
#PHASE 2 : compile the *.dsp files
#-------------------------------------------------------------------

CUR=$(pwd)
f=$(basename "$p")
SRCDIR=$(dirname "$p")
INPUT_FILE="$SRCDIR/$f"

# creates a dir 
TMP="${f%.dsp}"
mkdir -p "$TMP/tmp"

PROJECTDIR="$CUR/$TMP"
FAUST_MAIN_OUTPUT=$TMP/tmp/rendertmp.cpp
# compile faust to c++
faust $FAUST_ARGS -i -a $ARCHFILE $OPTIONS "$INPUT_FILE" -o "$FAUST_MAIN_OUTPUT"

EFFECT_OUTPUT=$TMP/effect.h
if [[ "$POLY" == *POLY2* ]]; then
	if [ $EFFECT = "auto" ]; then
		# Creer un fichier .dsp simple
		cat > $TMP/effect.dsp << EndOfCode
		adapt(1,1) = _;
		adapt(2,2) = _,_;
		adapt(1,2) = _ <: _,_;
		adapt(2,1) = _,_ :> _;

		adaptor(F,G) = adapt(outputs(F),inputs(G));

		process = adaptor(library("$INPUT_FILE").process, library("$INPUT_FILE").effect) : library("$INPUT_FILE").effect;
EndOfCode
		faust $FAUST_ARGS -i -cn effect -a minimal-effect.cpp "$TMP/effect.dsp" -o "$EFFECT_OUTPUT"

	else
		faust $FAUST_ARGS -i -cn effect -a minimal-effect.cpp "$EFFECT" -o "$EFFECT_OUTPUT"
	fi
fi

#-------------------------------------------------------------------
#PHASE 3 : Data for BELA
#-------------------------------------------------------------------

echo '// Options :' > "$PROJECTDIR/tmp.txt"
if [ $NVOICES -gt 0 ]; then
	echo '#define NVOICES '$NVOICES >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$MIDIDEFS" == *MIDI* ]]; then
	echo '#define MIDICTRL' >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$POLY" == *POLY2* ]]; then
	echo '#define POLY2' >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$OSCDEFS" == *OSC* ]]; then
	echo '#define OSCCTRL' >> "$PROJECTDIR/tmp.txt"
fi

if [[ "$GUIDEFS" == *GUI* ]]; then
	echo '#define HTTPDGUI' >> "$PROJECTDIR/tmp.txt"
	BELA_LDLIBS="$BELA_LDLIBS -lHTTPDFaust"
fi

if [[ "$SOUNDFILEDEFS" == *SOUNDFILE* ]]; then
    echo '#define SOUNDFILE' >> "$PROJECTDIR/tmp.txt"
    BELA_LDLIBS="$BELA_LDLIBS -lsndfile"
fi

cat "$FAUST_MAIN_OUTPUT" >> "$PROJECTDIR/tmp.txt"
mv "$PROJECTDIR/tmp.txt" "$PROJECTDIR/render.cpp"
rm -rf "$PROJECTDIR/tmp"

#-------------------------------------------------------------------
#PHASE 4 : SEND data to BELA and RUN it.
#-------------------------------------------------------------------

if [[ "$SEND2BELA" == *OK* ]]; then
	echo "Send to bela"
	echo $PROJECTDIR
	
#-------------------------------------------------------------------
#From build_project.sh :
#-------------------------------------------------------------------
echo "Start communication with bela"

BELA_EXPERT_MODE=0
BELA_DONT_RUN_FIRST=0

# FUNCTIONS:+++++++++++++++++++++++++++++++
check_rsync(){
	if [ -z "`which rsync 2> /dev/null`" ]
	then
		return 1
	else
		return 0
	fi
}

check_board_alive_and_set_date(){
	printf "Checking the board is up and running at $BBB_ADDRESS..."
	# Clear the host if it is cached in ~/.ssh/known_hosts.
	ssh-keygen -R $BBB_HOSTNAME &> /dev/null || true
	ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 $BBB_ADDRESS "date -s \"`date '+%Y%m%d %T %z'`\" > /dev/null" && printf "done\n" || {
		printf "\nERROR: the board does not respond at $BBB_ADDRESS, check that the address is correct and the board is connected.\n";
		exit 1;
	}
}

#+++++++++++++++++++++++++++++++++++++++++++

# Test if project folder contain correct file(s):
FIND_STRING="find $PROJECTDIR -maxdepth 1 -type f "
EXTENSIONS_TO_FIND='\.cpp\|\.c\|\.S\|\.pd\|\.scd'
FOUND_FILES=$($FIND_STRING 2>/dev/null | grep "$EXTENSIONS_TO_FIND")
if [ -z "$FOUND_FILES" ]
then
	printf "ERROR: Please provide a directory containing .c, .cpp, .S, .pd or .scd files.\n\n"
	exit 1
fi

[ -z $BBB_PROJECT_NAME ] && BBB_PROJECT_NAME="$(basename $(cd "$PROJECTDIR" && pwd))"

echo $PROJECTDIR
echo $BBB_PROJECT_NAME

BBB_PROJECT_FOLDER=$BBB_PROJECT_HOME"/"$BBB_PROJECT_NAME #make sure there is no trailing slash here
BBB_NETWORK_TARGET_FOLDER=$BBB_ADDRESS:$BBB_PROJECT_FOLDER

# The expert will have to remember to run set_date after powering up the board if needed
[ "$BELA_EXPERT_MODE" -eq 0 ] && check_board_alive_and_set_date

# Stop running process
echo "Stop running process..."
ssh $BBB_ADDRESS make QUIET=true --no-print-directory -C $BBB_BELA_HOME stop

# Check if rsync is available
check_rsync && RSYNC_AVAILABLE=1 || RSYNC_AVAILABLE=0

uploadBuildRun(){
	# Copy new source files to the board
	echo "uploadBuildRun START"
	printf "Copying new source files to BeagleBone..."
	if [ "$RSYNC_AVAILABLE" -eq 0 ];
	then
		echo "Using scp..."
		
		echo "Cleaning the destination folder..."
		#if rsync is not available, brutally clean the destination folder
		ssh $BBB_ADDRESS "rm -rf \"$BBB_PROJECT_FOLDER\"; mkdir -p \"$BBB_PROJECT_FOLDER\""
		echo "Copying the project files"
		scp -r $PROJECTDIR/* "$BBB_NETWORK_TARGET_FOLDER"
	else
		#rsync 
		# --delete makes sure it removes files that are not in the origin folder
		# -c evaluates changes using md5 checksum instead of file date, so we don't care about time skews 
		# --no-t makes sure file timestamps are not preserved, so that the Makefile will not think that targets are up to date when replacing files on the BBB
		#  with older files from the host. This will solve 99% of the issues with Makefile thinking a target is up to date when it is not.
		echo "Using rsync..."
		
		rsync -ac --out-format="   %n" --no-t --delete-after --exclude=$BBB_PROJECT_NAME --exclude=build --exclude=settings.json $PROJECTDIR"/" "$BBB_NETWORK_TARGET_FOLDER/" #trailing slashes used here make sure rsync does not create another folder inside the target folder
	fi

	if [ $? -ne 0 ]
	then
		printf "\nError while copying files\n"
		exit
	fi
	
	# Make new Bela executable and run
	MAKE_COMMAND="make --no-print-directory QUIET=true -C $BBB_BELA_HOME PROJECT='$BBB_PROJECT_NAME' CL='$COMMAND_ARGS' LDLIBS='$BELA_LDLIBS' CPPFLAGS='$BELA_CPPFLAGS' AT="
	
	ssh -t $BBB_ADDRESS "$MAKE_COMMAND run"
}

echo "Run bela now"
uploadBuildRun
	
fi
echo "$PROJECTDIR/render.cpp;"
