#!/bin/sh

check_os_arch(){
	if [ -x /usr/bin/lsb_release ]; then
		OS_DISTRIB=$(lsb_release -si|tr '[:upper:]' '[:lower:]')
		OS_VERSION=`lsb_release -sr`
	elif [ -e /etc/os-release ]; then
		OS_DISTRIB=$(cat /etc/os-release|grep '^ID='|cut -d '=' -f 2|sed s/\"//g|tr '[:upper:]' '[:lower:]')
		OS_VERSION=$(cat /etc/os-release|grep '^VERSION='|cut -d '=' -f 2|cut -d ' ' -f 1|sed s/\"//g)
	elif [ -e /etc/redhat-release ]; then
		OS_DISTRIB="centos"
		OS_VERSION=$(cat /etc/redhat-release|sed s/\ /\\\\n/g|grep '\.')
	else
		OS_DISTRIB=$(uname -s|tr '[:upper:]' '[:lower:]')
		OS_VERSION=$(uname -r)
	fi
	ARCH=$(uname -m)
	OS_NAME=$(uname -s)

	case $OS_DISTRIB in
		"redhatenterpriseclient" | "redhatenterpriseserver" | "rhel" | "scientificsl" | "scientific" | "centos" | "scientificfermi" | "scientificcernslc")
			OS_DISTRIB="RHEL"
			OS_VERSION=$(echo "${VERSION}" | cut -d '.' -f 1)
			;;
		"ubuntu")
			OS_DISTRIB="Ubuntu"
			;;
		"debian")
			OS_DISTRIB="Ubuntu"
			;;
		"linuxmint")
			OS_DISTRIB="Ubuntu"
			;;
		"freebsd")
			OS_DISTRIB="FreeBSD"
			OS_VERSION=$(uname -r | cut -d '.' -f 1)
			ARCH=$(uname -p)
			;;
		"darwin")
			OS_DISTRIB="OSX"
			OS_VERSION=$(uname -r | cut -d '.' -f 1)
			;;
		"linux")
			if echo $OS_VERSION | grep -q '\.el7\.\?'; then
				OS_DISTRIB="RHEL"
				OS_VERSION=7
			elif echo $OS_VERSION | grep -q '\.el6\.\?'; then
				OS_DISTRIB="RHEL"
				OS_VERSION=6
			elif echo $OS_VERSION | grep -q '\.el5\.\?'; then
				OS_DISTRIB="RHEL"
				OS_VERSION=5
			fi
	esac
	OS_ARCH=${OS_DISTRIB}_${OS_VERSION}_${ARCH}
}

check_pkgconfig(){
	if [ "$CHECKED_PKGCONFIG" ]; then return; fi
	echo "Looking for pkg-config..."
	PKG_CONFIG_BIN=$(which pkg-config 2>&1)
	if [ "$?" -ne 0 ]; then
		echo "Error: pkg-config not found; you will need to specify library locations manually" 1>&2
		exit 1
	fi
	echo " Found $PKG_CONFIG_BIN"
	CHECKED_PKGCONFIG=1
}

find_package(){
	PKG=$1
	VAR_PREFIX=`echo $PKG | tr [:lower:] [:upper:]`
	TMP_FOUND=`eval echo "$"${VAR_PREFIX}_FOUND`
	if [ "$TMP_FOUND" ]; then return; fi
	check_pkgconfig
	echo "Looking for $PKG..."

	pkg-config --exists $PKG
	if [ "$?" -ne 0 ]; then
		echo " $PKG not found with pkg-config"
		return
	fi
	if [ $# -ge 2 ]; then
		MIN_VERSION=$2
		pkg-config --atleast-version $MIN_VERSION $PKG
		if [ "$?" -ne 0 ]; then
			echo "Error: installed $PKG version ("`pkg-config --modversion $PKG`") is too old; version >=$MIN_VERSION is required" 1>&2
			exit 1
		fi
	fi
	echo " Found $PKG version `pkg-config --modversion $PKG`"
	eval ${VAR_PREFIX}_FOUND=1
	eval ${VAR_PREFIX}_VERSION=\"`pkg-config --modversion $PKG`\"
	eval ${VAR_PREFIX}_CFLAGS=\"`pkg-config --cflags $PKG`\"
	eval ${VAR_PREFIX}_LDFLAGS=\"`pkg-config --libs $PKG`\"
	eval ${VAR_PREFIX}_INCDIR=\"`pkg-config --variable=includedir $PKG`\"
	eval ${VAR_PREFIX}_LIBDIR=\"`pkg-config --variable=libdir $PKG`\"
}

find_hdf5(){
	PKG=hdf5
	echo "Looking for $PKG..."
	VAR_PREFIX=`echo $PKG | tr [:lower:] [:upper:]`
	TMP_FOUND=`eval echo "$"${VAR_PREFIX}_FOUND`
	if [ "$TMP_FOUND" ]; then return; fi

	which h5cc 2>&1 > /dev/null
	if [ "$?" -ne 0 ]; then return; fi

	which h5ls 2>&1 > /dev/null
	if [ "$?" -eq 0 ]; then
		HDF5_VERSION=`h5ls --version | sed 's/.* \([0-9.]*\)/\1/'`
		echo " Found $PKG version $HDF5_VERSION via executables in \$PATH"
		if [ $# -ge 1 ]; then
			MIN_VERSION=$1
			#TODO: actually check version
		fi
	else
		echo " h5ls not found; cannot check $PKG version"
		echo " Proceeding with unknown version and hoping for the best"
	fi
	HDF5_COMPILE_COMMAND=`h5cc -show`
	for item in $HDF5_COMPILE_COMMAND; do
		item=`echo "$item" | sed 's| |\n|g' | sed -n 's/.*-L\([^ ]*\).*/\1/p'`
		if [ -n "$item" ]; then
			POSSIBLE_HDF5_LIBDIRS="$POSSIBLE_HDF5_LIBDIRS
				$item"
		fi
	done
	for HDF5_LIBDIR in $POSSIBLE_HDF5_LIBDIRS; do
		if [ -d $HDF5_LIBDIR -a \( -e $HDF5_LIBDIR/libhdf5.a -o -e $HDF5_LIBDIR/libhdf5.so \) ]; then
			break
		fi
	done
	if [ ! -d $HDF5_LIBDIR -o ! \( -e $HDF5_LIBDIR/libhdf5.a -o -e $HDF5_LIBDIR/libhdf5.so \) ]; then
		echo " Unable to guess $PKG library directory"
		return
	fi
	POSSIBLE_HDF5_INCDIRS=`echo "$HDF5_COMPILE_COMMAND" | sed 's| |\n|g' | sed -n 's/.*-I\([^ ]*\).*/\1/p'`
	POSSIBLE_HDF5_INCDIRS="$POSSIBLE_HDF5_INCDIRS ${HDF5_LIBDIR}/../include"
	for HDF5_INCDIR in $POSSIBLE_HDF5_INCDIRS; do
		if [ -d $HDF5_INCDIR -a -e $HDF5_INCDIR/H5version.h ]; then
			break
		fi
	done
	if [ ! -d $HDF5_INCDIR -o ! $HDF5_INCDIR/H5version.h ]; then
		echo " ERROR: Unable to guess $PKG include directory"
		return
	fi

	HDF5_CFLAGS="-I${HDF5_INCDIR}"
	HDF5_LDFLAGS=`echo "$HDF5_COMPILE_COMMAND" | \
	sed 's/ /\\
	/g' | \
	sed -n -E \
	-e '/^[[:space:]]*-l/p' \
	-e '/^[[:space:]]*-L/p' \
	-e '/^[[:space:]]*-Wl,/p' \
	-e 's/^[[:space:]]*.*lib([^.]*)\.a/-l\1/p' \
	-e 's/^[[:space:]]*.*lib([^.]*)\.so/-l\1/p' \
	-e 's/^[[:space:]]*.*lib([^.]*)\.dylib/-l\1/p' `
	HDF5_LDFLAGS=`echo $HDF5_LDFLAGS` # collapse to single line

	HDF5_FOUND=1
}

# less searching for python than verfying that the given executable works and extracting relevant paths
try_find_python(){
	echo "Looking for python"

	if command -v "${PYTHON_EXE}" > /dev/null 2>&1; then
		PYTHON_EXE=$(command -v ${PYTHON_EXE} 2>/dev/null)
		echo " Using python executable ${PYTHON_EXE}"
	else
		echo " ${PYTHON_EXE} is not a valid python executable"
		return
	fi

	PYTHON_VERSION=$("${PYTHON_EXE}" -c 'import sys; print(str(sys.version_info.major)+"."+str(sys.version_info.minor))')
	if [ "$?" -ne 0 ]; then
		echo " ERROR: Unable to use python executable ${PYTHON_EXE} (version check failed)"
		return
	fi
	PYTHONVERSIONSIMPLE=`${PYTHON_EXE} -c 'import sys; print(str(sys.version_info.major)+str(sys.version_info.minor))'`
	
	PYTHON_INCDIR=$(${PYTHON_EXE} -c "try:
 import sysconfig
 print(sysconfig.get_path('include'))
except ImportError:
 from distutils.sysconfig import get_python_inc
 print(get_python_inc())")
	if [ -d "$PYTHON_INCDIR" ]; then
		echo " Found python include dir $PYTHON_INCDIR"
	else
		echo " ERROR: Unable to locate the python include dir"
		return
	fi

	# This is the directory to which libraries should be installed for python to find them
	PYTHON_MODULEDIR=$(${PYTHON_EXE} -c "try:
 import sysconfig
 print(sysconfig.get_path('platlib'))
except ImportError:
 from distutils.sysconfig import get_python_lib
 print(get_python_lib(plat_specific=True, standard_lib=False))")
	if [ "$PYTHON_MODULEDIR" ]; then
		echo " Python module install dir is $PYTHON_MODULEDIR"
	else
		echo " ERROR: Unable to locate the python module dir"
		return
	fi
	
	# This is the directory that python claims contains its standard library, 
	# which may or may not include the actual libpython
	PYTHON_STDLIBDIR=$(${PYTHON_EXE} -c "try:
 import sysconfig
 print(sysconfig.get_path('stdlib'))
except ImportError:
 from distutils.sysconfig import get_python_lib
 print(get_python_lib(plat_specific=True, standard_lib=True))")
	# This may contain a suffix which appears after the version like in 'libpython3.6m'
	# See https://www.python.org/dev/peps/pep-3149/#proposal
	PYTHONLIBSUFFIX=$("${PYTHON_EXE}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")')
	PYTHONLIBSUFFIX=$(${PYTHON_EXE} -c "try:
 import sysconfig
 print(sysconfig.get_config_var('ABIFLAGS') or '')
except ImportError:
 from distutils.sysconfig import get_config_var
 print(get_config_var('ABIFLAGS') or '')")
	
	PYTHON_INCDIR=$("${PYTHON_EXE}" -c 'import sysconfig; print(sysconfig.get_path("include"))')
	if [ -d "$PYTHON_INCDIR" -a -f "${PYTHON_INCDIR}/Python.h" ]; then
		echo " Found python include dir $PYTHON_INCDIR"
	else
		# Sometimes (e.g. Apple dev tools pythons 3) sysconfig.get_path("include") is just a lie.
		# If it didn't help try using basically the logic distutils.sysconfig used
		PYTHON_INCDIR=$("${PYTHON_EXE}" -c 'import sys; print(sys.base_prefix)')"/include/python${PYTHON_VERSION}${PYTHONLIBSUFFIX}"
		if [ -d "$PYTHON_INCDIR" -a -f "${PYTHON_INCDIR}/Python.h" ]; then
			echo " Found python include dir $PYTHON_INCDIR"
		else
			echo " Unable to locate the python include dir"
			return
		fi
	fi
	
	# This is the directory that python claims contains its standard library, 
	# which may or may not include the actual libpython
	PYTHON_STDLIBDIR=$("${PYTHON_EXE}" -c 'import sysconfig; print(sysconfig.get_path("platstdlib"))')
	POSSIBLE_PYTHON_LIBDIRS="${PYTHON_STDLIBDIR} ${PYTHON_STDLIBDIR}/lib"
	# Using venv makes sysconfig.get_path("platstdlib") point to a directory which often  does not
	# contain the python library itself, so try off of the base prefix as well
	POSSIBLE_PYTHON_LIBDIRS="$POSSIBLE_PYTHON_LIBDIRS "$("${PYTHON_EXE}" -c 'import sys; print(sys.base_prefix)')"/lib"
	# or maybe the python library is just in a common system location?
	POSSIBLE_PYTHON_LIBDIRS="${POSSIBLE_PYTHON_LIBDIRS} /lib /lib64 /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64"
	# Ubuntu is special, of course
	if [ $OS_DISTRIB = "Ubuntu" ]; then
		POSSIBLE_PYTHON_LIBDIRS="${POSSIBLE_PYTHON_LIBDIRS} /usr/lib/$(uname -i)-linux-gnu"
	fi

	for PYTHON_LIBDIR in $POSSIBLE_PYTHON_LIBDIRS; do
		for PV in $PYTHON_VERSION $PYTHONVERSIONSIMPLE; do
			#echo "  Looking for ${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.(a|so|dylib)"
			if [ -d $PYTHON_LIBDIR ]; then
				if [ -e ${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.a ]; then
					PYTHON_LIBRARY=${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.a
					break
				elif [ -e ${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.so ];then
					PYTHON_LIBRARY=${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.so
					break
				elif [ -e ${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.dylib ]; then
					PYTHON_LIBRARY=${PYTHON_LIBDIR}/libpython${PV}${PYTHONLIBSUFFIX}.dylib
					break
				fi
			fi
		done
		if [ "$PYTHON_LIBRARY" ]; then break; fi
	done
	if [ -e "$PYTHON_LIBRARY" ]; then
		echo " Found python library $PYTHON_LIBRARY"
		PYTHON_LDFLAGS="-L${PYTHON_LIBDIR} -l$(echo "$PYTHON_LIBRARY" | sed 's|.*lib\(python.*\)\.[a-z]*|\1|')"
	else
		# For pybind11 builds, we don't actually need libpython - pybind11 modules
		# use -undefined dynamic_lookup on macOS or no python linking on Linux.
		# This is common in manylinux containers where libpython isn't available.
		echo " Note: libpython not found (this is OK for pybind11 builds)"
		PYTHON_LDFLAGS=""
	fi

	PYTHON_CFLAGS="-I${PYTHON_INCDIR}"
	PYTHON_FOUND=1
}

try_find_boost(){
	PKG=boost
	VAR_PREFIX=`echo $PKG | tr [:lower:] [:upper:]`
	TMP_FOUND=`eval echo "$"${VAR_PREFIX}_FOUND`
	if [ "$TMP_FOUND" ]; then return; fi
	if [ "$PYTHON_FOUND" ]; then
		PYV=`${PYTHON_EXE} -c 'import sys; print(str(sys.version_info.major)+str(sys.version_info.minor))'`
		PYVM=`${PYTHON_EXE} -c 'import sys; print(sys.version_info.major)'`
		echo "Looking for $PKG built for python ${PYV} in $GUESS_DIR..."
	else
		echo "Looking for $PKG in $GUESS_DIR..."
	fi
	
 	if [ "$#" -eq 1 ]; then
 		GUESS_DIR=$1
 		POSSIBLE_BOOST_LIBDIRS="${GUESS_DIR}/lib ${GUESS_DIR}/lib64 ${GUESS_DIR}/lib/${ARCH}-linux-gnu"
		POSSIBLE_BOOST_INCDIRS="${GUESS_DIR}/include"
	elif [ "$#" -eq 2 ]; then
		GUESS_DIR="$1 and $2"
		POSSIBLE_BOOST_LIBDIRS="$2"
		POSSIBLE_BOOST_INCDIRS="$1"
	else
		echo " ERROR: Wrong number of arguments to try_find_boost"
		return
 	fi
	if [ "$PYTHON_FOUND" ]; then
		for PYV_SUFFIX in $PYV $PYVM $PYV-mt $PVM-mt ''; do
			for BOOST_LIBDIR in $POSSIBLE_BOOST_LIBDIRS; do
				if [ -d $BOOST_LIBDIR -a \( -e $BOOST_LIBDIR/libboost_python${PYV_SUFFIX}.a -o -e $BOOST_LIBDIR/libboost_python${PYV_SUFFIX}.so -o -e $BOOST_LIBDIR/libboost_python${PYV_SUFFIX}.dylib \) ]; then
					if [ ! "$PYV_SUFFIX" ]; then
						echo " Found boost_python with no python version tag; hoping it is compatible"
					fi
					BOOST_PYTHON_FOUND=1
					BOOST_PYTHON_LDFLAGS="-lboost_python${PYV_SUFFIX}"
					break
				fi
			done
			if [ "$BOOST_PYTHON_FOUND" ]; then break; fi
		done
		if [ ! "$BOOST_PYTHON_FOUND" ]; then
			echo " ERROR: Unable to locate the boost_python library in $GUESS_DIR"
		fi
	fi
	for BOOST_INCDIR in $POSSIBLE_BOOST_INCDIRS; do
		if [ -d $BOOST_INCDIR -a -e $BOOST_INCDIR/boost/version.hpp ]; then
			break
		fi
	done
	if [ ! -d "$BOOST_INCDIR" -o ! -e "$BOOST_INCDIR/boost/version.hpp" ]; then
		echo " ERROR: Unable to locate boost/version.hpp in $GUESS_DIR"
		return
	fi
	BOOST_CFLAGS="-I${BOOST_INCDIR}"
	BOOST_LDFLAGS="-Wl,-rpath -Wl,${BOOST_LIBDIR} -L${BOOST_LIBDIR}"
	BOOST_FOUND=1
	echo " Found boost in $GUESS_DIR"
	echo " Boost include directory is ${BOOST_INCDIR}"
	if [ "$BOOST_LIBDIR" ]; then
		echo " Boost library directory is ${BOOST_LIBDIR}"
	fi
}

find_numpy(){
	echo "Looking for numpy..."
	NUMPY_INCDIR=$(${PYTHON_EXE} -c 'import numpy; print(numpy.get_include())')
	if [ "$?" -ne 0 ]; then
		echo " ERROR: Unable to import numpy using ${PYTHON_EXE}"
		return
	fi
	NUMPY_CFLAGS="-I${NUMPY_INCDIR}"
	NUMPY_FOUND=1
	echo " Found numpy"
	echo " Numpy include directory is ${NUMPY_INCDIR}"
}

ensure_found(){
	PKG=$1
	VAR_PREFIX=`echo $PKG | tr [:lower:] [:upper:]`
	TMP_FOUND=`eval echo "$"${VAR_PREFIX}_FOUND`
	if [ "$TMP_FOUND" ]; then return; fi
	#not found
	lowername=`echo $PKG | tr [A-Z] [a-z]`

	TMP_INCDIR=`eval echo "$"${VAR_PREFIX}_INCDIR`
	TMP_LIBDIR=`eval echo "$"${VAR_PREFIX}_LIBDIR`
	if [ "$TMP_INCDIR" -a "$TMP_LIBDIR" ]; then
		echo "Error: $PKG not found in $TMP_INCDIR and $TMP_LIBDIR or with pkg-config" 1>&2
		echo "Please verify that the path given to --with-${lowername} is correct" 1>&2
	else
		echo "Error: $PKG not installed or not registered with pkg-config" 1>&2
		echo "Please specify location using the --with-${lowername} flag" 1>&2
	fi
	unset TMP_INCDIR
	unset TMP_LIBDIR
	exit 1
}

PREFIX=/usr/local
INSTALL_LIBDIR=lib
INSTALL_BINDIR=bin

VERSION_NUM=101302
VERSION_MAJOR=$(echo $VERSION_NUM | awk '{print int($1/100000)}')
VERSION_MINOR=$(echo $VERSION_NUM | awk '{print int($1/100)%1000}')
VERSION_PATCH=$(echo $VERSION_NUM | awk '{print $1%100}')
VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"

check_os_arch

if command -v "gcc" > /dev/null 2>&1; then
	GUESS_CC=gcc
elif command -v "clang" > /dev/null 2>&1; then
	GUESS_CC=clang
elif command -v "cc" > /dev/null 2>&1; then
	GUESS_CC=cc
fi
if command -v "g++" > /dev/null 2>&1; then
	GUESS_CXX=g++
elif command -v "clang++" > /dev/null 2>&1; then
	GUESS_CXX=clang++
elif command -v "c++" > /dev/null 2>&1; then
	GUESS_CXX=c++
fi
GUESS_AR=ar
GUESS_LD=ld
if [ "$OS_NAME" = Linux ]; then
	DYN_SUFFIX=.so
	DYN_SUFFIX_FULL_VERSION='${DYN_SUFFIX}.$(VERSION)'
	DYN_SUFFIX_MAJOR_VERSION='${DYN_SUFFIX}.$(VERSION_MAJOR)'
	DYN_OPT='-shared -Wl,-soname,$(shell basename $(DYN_PRODUCT))'
	DYN_OPT_PY='-shared -Wl,-soname,$(shell basename $(PYTHON_LIB))'
fi
if [ "$OS_NAME" = Darwin ]; then
	GUESS_CC=clang
	GUESS_CXX=clang++
	GUESS_LD=clang++
	DYN_SUFFIX=.dylib
	DYN_SUFFIX_FULL_VERSION='.$(VERSION)${DYN_SUFFIX}'
	DYN_SUFFIX_MAJOR_VERSION='.$(VERSION_MAJOR)${DYN_SUFFIX}'
	# -headerpad_max_install_names ensures there's room for install_name_tool to rewrite paths
	# (needed for pip installs which use long temp directory paths)
	DYN_OPT='-dynamiclib -compatibility_version $(COMPAT_VERSION) -current_version $(VERSION) -Wl,-headerpad_max_install_names'
	DYN_OPT_PY='-dynamiclib -compatibility_version $(COMPAT_VERSION) -current_version $(VERSION) -Wl,-headerpad_max_install_names'
fi

CC=${CC-$GUESS_CC}
CXX=${CXX-$GUESS_CXX}
AR=${AR-$GUESS_AR}
LD=${LD-$GUESS_LD}

PYTHON_EXE="python"
if which "$PYTHON_EXE" > /dev/null 2>&1; then
	: # good, keep our initial guess
elif which "python3" > /dev/null 2>&1; then
	PYTHON_EXE="python3"
fi

HELP="Usage: ./configure [OPTION]... 

Installation directories:
  --prefix=PREFIX         install files in PREFIX
                          [$PREFIX]

By default, \`make install' will install all the files in
\`$PREFIX/bin', \`$PREFIX/lib' etc.  You can specify
an installation prefix other than \`$PREFIX' using \`--prefix',
for instance \`--prefix=\$HOME'.

Fine tuning of the installation directories:

  --libdir=DIR            object code libraries [lib]
  --bindir=DIR            executable scripts like nusquids-config [bin]

The following options can be used to maunally specify the 
locations of dependencies:
  --with-gsl=DIR                 use the copy of GSL in DIR
                                 assuming headers are in DIR/include
                                 and libraries in DIR/lib
  --with-gsl-incdir=DIR          use the copy of GSL in DIR
  --with-gsl-libdir=DIR          use the copy of GSL in DIR
  --with-hdf5=DIR                use the copy of HDF5 in DIR
                                 assuming headers are in DIR/include
                                 and libraries in DIR/lib
  --with-hdf5-incdir=DIR         use the copy of HDF5 in DIR
  --with-hdf5-libdir=DIR         use the copy of HDF5 in DIR
  --with-squids=DIR              use the copy of SQuIDS in DIR
                                 assuming headers are in DIR/include
                                 and libraries in DIR/lib
  --with-squids-incdir=DIR       use the copy of SQuIDS in DIR
  --with-squids-libdir=DIR       use the copy of SQuIDS in DIR
For the python bindings the following flags are used:
  --with-python-bindings         enable python binding compilation
  --with-pybind-incdir=DIR       use the copy of pybind11 in DIR
  --with-boost-python-bindings	 uses the legacy Boost.Python bindings
  --with-boost-incdir=DIR        use the copy of Boost in DIR
  --with-boost-libdir=DIR        use the copy of Boost in DIR
  --with-boost=DIR               use the copy of Boost in DIR
                                 assuming headers are in DIR/include
                                 and libraries in DIR/lib
  --python-bin=PYTHON_EXECUTABLE use this python executable
                                 (default is 'python')
  --python-config=PYTHON_CONFIG  use this python-config to determine compilation and linking settings
                                 (default is 'python-config')
  --python-module-dir=DIR        install python module to this directory, rather
                                 than the default system location. The special 
                                 value site.USER_SITE will be automatically
                                 expanded using the python interpreter

Some influential environment variables:
CC          C compiler command
CXX         C++ compiler command
AR          Static linker command
LD          Dynamic linker command
" #`

for var in "$@"
do
	if [ "$var" = "--help" -o "$var" = "-h" ]; then
		echo "$HELP"
		exit 0
	fi

	TMP=`echo "$var" | sed -n 's/^--prefix=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then PREFIX="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--libdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then INSTALL_LIBDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--bindir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then INSTALL_BINDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-gsl=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then
		GSL_INCDIR="${TMP}/include";
		GSL_LIBDIR="${TMP}/lib";
	continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-gsl-incdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then GSL_INCDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-gsl-libdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then GSL_LIBDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-hdf5=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then
		HDF5_INCDIR="${TMP}/include";
		HDF5_LIBDIR="${TMP}/lib";
	continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-hdf5-incdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then HDF5_INCDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-hdf5-libdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then HDF5_LIBDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-squids=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then
		SQUIDS_INCDIR="${TMP}/include";
		SQUIDS_LIBDIR="${TMP}/lib";
	continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-squids-incdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then SQUIDS_INCDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-squids-libdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then SQUIDS_LIBDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-python-bindings/true/p'`
	if [ "$TMP" ]; then PYTHON_BINDINGS=true; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-pybind-incdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then PYBIND_INCDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-boost-python-bindings/true/p'`
	if [ "$TMP" ]; then BOOST_PYTHON_BINDINGS=true; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-boost=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then
		BOOST_INCDIR="${TMP}/include";
		BOOST_LIBDIR="${TMP}/lib";
	continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-boost-libdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then BOOST_LIBDIR="$TMP"; continue; fi
	TMP=`echo "$var" | sed -n 's/^--with-boost-incdir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then BOOST_INCDIR="$TMP"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--python-bin=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then PYTHON_EXE=$TMP; continue; fi

	TMP=`echo "$var" | sed -n 's/^--python-config=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then PYTHON_CONFIG=$TMP; continue; fi

	TMP=`echo "$var" | sed -n 's/^--python-module-dir=\(.*\)$/\1/p'`
	if [ "$TMP" ]; then USER_PYTHON_MODULE_DIR="${TMP}"; continue; fi

	TMP=`echo "$var" | sed -n 's/^--with-julia-bindings/true/p'`
	if [ "$TMP" ]; then JULIA_BINDINGS=true; continue; fi

	echo "config.sh: Unknown or malformed option '$var'" 1>&2
	exit 1
done

if [ "$GSL_INCDIR" -a "$GSL_LIBDIR" ]; then
	echo "Checking manually specified GSL..."
	if [ -d "$GSL_INCDIR/gsl" \
         -a -e "$GSL_INCDIR/gsl/gsl_version.h" \
         -a -d "$GSL_LIBDIR" \
         -a -e "$GSL_LIBDIR/libgsl.a" ]; then
		GSL_FOUND=1
		GSL_CFLAGS="-I$GSL_INCDIR"
		GSL_LDFLAGS="-L$GSL_LIBDIR -lgsl -lgslcblas -lm"
	else
		echo "Warning: manually specifed GSL not found; will attempt auto detection"
	fi
fi

find_package gsl 1.15

if [ "$HDF5_INCDIR" -a "$HDF5_LIBDIR" ]; then
	echo "Checking manually specified HDF5..."
	if [ -d "$HDF5_INCDIR" \
         -a -e "$HDF5_INCDIR/H5version.h" \
         -a -d "$HDF5_LIBDIR" \
         -a -e "$HDF5_LIBDIR/libhdf5.a" \
         -a -e "$HDF5_LIBDIR/libhdf5_hl.a" ]; then
		HDF5_FOUND=1
		HDF5_CFLAGS="-I$HDF5_INCDIR"
		HDF5_LDFLAGS="-L$HDF5_LIBDIR -lhdf5 -lhdf5_hl"
	else
		echo "Warning: manually specifed HDF5 not found; will attempt auto detection"
	fi
fi

#Do not use this due to broken Ubuntu package
#find_package hdf5 1.8
find_hdf5

if [ "$SQUIDS_INCDIR" -a "$SQUIDS_LIBDIR" ]; then
	echo "Checking manually specified SQUIDS..."
	if [ -d "$SQUIDS_INCDIR" \
         -a -d "$SQUIDS_LIBDIR" \
         -a -e "$SQUIDS_LIBDIR/libSQuIDS.a" ]; then
		SQUIDS_FOUND=1
		SQUIDS_CFLAGS="-I$SQUIDS_INCDIR"
		SQUIDS_LDFLAGS="-L$SQUIDS_LIBDIR -lSQuIDS"
		if $CXX --version | grep -q "Free Software Foundation"; then
			SQUIDS_CFLAGS="$SQUIDS_CFLAGS -Wno-abi"
		fi
	else
		echo "Warning: manually specifed SQUIDS not found; will attempt auto detection"
	fi
fi

find_package squids 1.2

if [ "$PYTHON_BINDINGS" -o "$BOOST_PYTHON_BINDINGS" ]; then
	try_find_python
	if [ "$PYTHON_FOUND" != 1 ]; then
		echo "*** Failed to find python; python bindings will not be built ***"
		unset PYTHON_BINDINGS
	else
		if [ "$USER_PYTHON_MODULE_DIR" ]; then
			if [ "$USER_PYTHON_MODULE_DIR" == "site.USER_SITE" ]; then
				PYTHON_MODULEDIR=`${PYTHON_EXE} -c 'import site; print(site.USER_SITE)'`
			else
				PYTHON_MODULEDIR="$USER_PYTHON_MODULE_DIR"
			fi
		fi
	fi

	if [ "$PYTHON_CONFIG" ]; then
		echo "Using provided python-config to set compilation python-bindings flags"
		PYTHON_CFLAGS=`$PYTHON_CONFIG --includes`
		# -undefined dynamic_lookup is macOS-specific; on Linux use --ldflags from python-config
		if [ "$OS_NAME" = Darwin ]; then
			PYTHON_LDFLAGS='-undefined dynamic_lookup'
		else
			PYTHON_LDFLAGS=`$PYTHON_CONFIG --ldflags 2>/dev/null || echo ""`
		fi
	fi

	if [ "$PYTHON_BINDINGS" -a "$BOOST_PYTHON_BINDINGS" ]; then
		echo "Warning: simultanenously specified pybind and boost python bindings options. Ignoring Boost Python binding option. If you want to use the Boost Python bindings do not include the --with-python-bindings flag and only use --with-boost-python-bindings."
		unset $BOOST_PYTHON_BINDINGS
	fi

	if [ $BOOST_PYTHON_BINDINGS ]; then
		# Boost.Python actually requires libpython, unlike pybind11
		if [ -z "$PYTHON_LIBRARY" -a -z "$PYTHON_LDFLAGS" ]; then
			echo "*** Boost.Python requires libpython which was not found; python bindings will not be built ***"
			unset BOOST_PYTHON_BINDINGS
			unset PYTHON_BINDINGS
		else
			if [ "$BOOST_INCDIR" -a "$BOOST_LIBDIR" ]; then
				echo "Checking manually specified boost..."
				try_find_boost "$BOOST_INCDIR" "$BOOST_LIBDIR"
				if [ ! "$BOOST_FOUND" ]; then
					echo "Warning: manually specifed boost not found; will attempt auto detection"
				fi
			fi
			try_find_boost /usr
			try_find_boost /usr/local
			if [ "$BOOST_PYTHON_FOUND" != 1 ]; then
				echo "*** Failed to find boost python; python bindings will not be built ***"
				unset PYTHON_BINDINGS
			fi
		fi
	else
		if [ "$PYBIND_INCDIR" ]; then 
			if [ ! -d "$PYBIND_INCDIR" -o ! -e "$PYBIND_INCDIR/pybind11/pybind11.h" ]; then
				echo " *** Failed to find pybind11/pybind11.h in $PYBIND_INCDIR; python bindings will not be build ***"
				unset PYTHON_BINDINGS
			else
				echo "Using provided pybind11 header directory $PYBIND_INCDIR"
				PYBIND_CFLAGS=-I$PYBIND_INCDIR
			fi
		else
			echo "Autodetecting pybind11 header directory using ${PYTHON_EXE} executable..."
			PYBIND_CFLAGS=$(${PYTHON_EXE} -m pybind11 --includes 2>/dev/null)
			PYBIND_INCLUDE=$(echo "$PYBIND_CFLAGS" | sed -E 's/.*-I([^ ]*pybind11[^ ]*).*/\1/')

			if [ $? -ne 0 ] || [ -z "$PYBIND_CFLAGS" ]; then
			    echo " ERROR: pybind11 not found for Python executable ${PYTHON_EXE}."
			    echo " Please install it using: ${PYTHON_EXE} -m pip install pybind11"
		            echo "*** Failed to find pybind11; python bindings will not be built ***"
		            unset PYTHON_BINDINGS
		        else
			echo " Found pybind11 headers in $PYBIND_INCLUDE"
			fi
		fi
	fi

	find_numpy
	if [ "$NUMPY_FOUND" != 1 ]; then
		echo "*** Failed to find numpy; python bindings will not be built ***"
		unset PYTHON_BINDINGS
	fi
fi

ensure_found gsl
ensure_found hdf5
ensure_found squids

# Resolve PREFIX absolutely
OLDPWD=`pwd`
cd "$PREFIX"
PREFIX=`pwd`
cd "$OLDPWD"

SOURCE_PATH=`pwd`

if [ ! -d ./build/ ]; then
    mkdir build;
fi
if [ ! -d ./lib/ ]; then
    mkdir lib;
fi

echo "Generating nusquids-config script..."
cat > lib/nusquids-config << NUSQUIDS_CONFIG_EOF
#!/bin/bash
# nuSQuIDS configuration script
# Generated by configure

prefix="${PREFIX}"
libdir="\${prefix}/${INSTALL_LIBDIR}"
includedir="\${prefix}/include"
version="${VERSION}"

# Dependency flags (resolved at configure time)
SQUIDS_CFLAGS="${SQUIDS_CFLAGS}"
SQUIDS_LDFLAGS="${SQUIDS_LDFLAGS}"
GSL_CFLAGS="${GSL_CFLAGS}"
GSL_LDFLAGS="${GSL_LDFLAGS}"
HDF5_CFLAGS="${HDF5_CFLAGS}"
HDF5_LDFLAGS="${HDF5_LDFLAGS}"

usage() {
    cat <<EOF
Usage: nusquids-config [OPTIONS]
Options:
  --prefix       Print installation prefix
  --incdir       Print include directory
  --libdir       Print library directory
  --cflags       Print compiler flags (includes dependencies)
  --libs         Print linker flags (includes dependencies)
  --version      Print nuSQuIDS version
  --help         Print this message
EOF
    exit \$1
}

if [ \$# -eq 0 ]; then
    usage 1
fi

while [ \$# -gt 0 ]; do
    case "\$1" in
        --prefix)
            echo "\$prefix"
            ;;
        --incdir)
            echo "\$includedir"
            ;;
        --libdir)
            echo "\$libdir"
            ;;
        --cflags)
            echo "-I\${includedir} \${SQUIDS_CFLAGS} \${GSL_CFLAGS} \${HDF5_CFLAGS}"
            ;;
        --libs)
            echo "-L\${libdir} -lnuSQuIDS \${SQUIDS_LDFLAGS} \${GSL_LDFLAGS} \${HDF5_LDFLAGS}"
            ;;
        --version)
            echo "\$version"
            ;;
        --help)
            usage 0
            ;;
        *)
            echo "Unknown option: \$1" 1>&2
            usage 1
            ;;
    esac
    shift
done
NUSQUIDS_CONFIG_EOF
chmod +x lib/nusquids-config

echo "Generating config file..."

# Somewhat evil: HDF5 does not register with pkg-config, which causes the latter
# to error out because it cannot find nuSQuIDS dependencies.
# Solution: Since we found HDF5 (hopefully correctly), register it ourselves.
echo "# WARNING: This configuration file was heutristically generated by nuSQuIDS
# and may not be complete or correct
libdir=${HDF5_LIBDIR}
includedir=${HDF5_INCDIR}" > lib/hdf5.pc
echo '
Name: HDF5
Description: "A data model, library, and file format for storing and managing data."
URL: https://www.hdfgroup.org/HDF5/' >> lib/hdf5.pc
echo "Version: ${HDF5_VERSION}" >> lib/hdf5.pc
echo "Cflags: ${HDF5_CFLAGS}
Libs: ${HDF5_LDFLAGS}
" >> lib/hdf5.pc

echo "prefix=$PREFIX" > lib/nusquids.pc
echo '
libdir=${prefix}/'"$INSTALL_LIBDIR"'
includedir=${prefix}/include

Name: nuSQuIDS
Description: Toolbox for neutrino oscillation experiments
URL: https://github.com/arguelles/nuSQuIDS' >> lib/nusquids.pc
echo "Version: $VERSION" >> lib/nusquids.pc
echo 'Requires: gsl >= 1.15 hdf5 >= 1.8 squids >= 1.2.0
Libs: -L${libdir} -lnuSQuIDS
Cflags: -I${includedir}
' >> lib/nusquids.pc

echo "Generating version header..."
sed -e "s|__NUSQUIDS_VERSION__|$VERSION_NUM|g" \
    -e "s|__NUSQUIDS_VERSION_STR__|$VERSION|g" \
    < resources/version.h.in > include/nuSQuIDS/version.h

INSTALL_FLAG_PREFIX="NUSQUIDS_DATA_PATH_INSTALL_FLAG_PREFIX_"
INSTALL_FLAG_SUFFIX="_NUSQUIDS_DATA_PATH_INSTALL_FLAG_SUFFIX"
INSTALL_FLAG_OFF="A"
INSTALL_FLAG_ON="B"
REPLACE_INSTALL_FLAG="s|${INSTALL_FLAG_PREFIX}${INSTALL_FLAG_OFF}${INSTALL_FLAG_SUFFIX}|${INSTALL_FLAG_PREFIX}${INSTALL_FLAG_ON}${INSTALL_FLAG_SUFFIX}|g"

echo "Generating data path header..."
echo "#include <cstring>
#define SOURCE_DATA_PATH \"${SOURCE_PATH}/data/\"
#define INSTALL_DATA_PATH \"${PREFIX}/share/nuSQuIDS/\"

namespace{

const char dataPathBitOffValue='$INSTALL_FLAG_OFF';
//This needs to be volatile so that the compiler can't optimize away reads from it,
//which is important since we plan to change the value of the constant between compile-time 
//and run-time
const volatile char dataPathBitContainer[] = \"${INSTALL_FLAG_PREFIX}${INSTALL_FLAG_OFF}${INSTALL_FLAG_SUFFIX}\";

bool getInstallBit(){
	static const std::size_t prefixLen = strlen(\"${INSTALL_FLAG_PREFIX}\");
	return dataPathBitContainer[prefixLen]!='${INSTALL_FLAG_OFF}';
}

}

" > build/resource_paths.h

echo "Generating makefile..."
echo "# Compiler
CC=$CC
CXX=$CXX
AR=$AR
LD=$LD

VERSION:=$VERSION
VERSION_MAJOR:=$VERSION_MAJOR
COMPAT_VERSION:=${VERSION_MAJOR}.${VERSION_MINOR}
LIBDIR:=lib
INCDIR:=include
NUSQINCDIR:=include/nuSQuIDS
SRCDIR:=src
PREFIX:=$PREFIX
INSTALL_LIBDIR:=$INSTALL_LIBDIR
INSTALL_BINDIR:=$INSTALL_BINDIR

DYN_SUFFIX=$DYN_SUFFIX
DYN_SUFFIX_FULL_VERSION:=$DYN_SUFFIX_FULL_VERSION
DYN_SUFFIX_MAJOR_VERSION:=$DYN_SUFFIX_MAJOR_VERSION
DYN_OPT=$DYN_OPT
DYN_OPT_PY=$DYN_OPT_PY

" > ./Makefile

echo '
PATH_nuSQUIDS=$(shell pwd)
PATH_SQUIDS=$(SQUIDS_DIR)

SOURCES = $(wildcard src/*.cpp)
OBJECTS = $(patsubst src/%.cpp,build/%.o,$(SOURCES))

EXAMPLES := examples/Single_energy/single_energy \
            examples/Multiple_energy/multiple_energy \
            examples/Atm_default/atm_default \
            examples/Bodies/bodies \
            examples/Xsections/xsections \
            examples/NSI/nsi \
            examples/LV/lv \
            examples/Atm_BSM/atm_bsm\
            examples/HDF5_Write_Read/write \
            examples/HDF5_Write_Read/read \
            examples/Constant_density_layers/const_dens_layers \
            examples/Astrophysical_neutrino_flavor_ratio/astro_flv_ratio \
            examples/Decoherence/decoherence

CXXFLAGS= -std=c++11

# Directories
'  >> ./Makefile
echo "GSL_CFLAGS=$GSL_CFLAGS" >> ./Makefile
echo "GSL_LDFLAGS=$GSL_LDFLAGS" >> ./Makefile

echo "HDF5_CFLAGS=$HDF5_CFLAGS" >> ./Makefile
echo "HDF5_LDFLAGS=$HDF5_LDFLAGS" >> ./Makefile

echo "SQUIDS_CFLAGS=$SQUIDS_CFLAGS" >> ./Makefile
echo "SQUIDS_LDFLAGS=$SQUIDS_LDFLAGS" >> ./Makefile

if [ "$PYTHON_BINDINGS" -o "$BOOST_PYTHON_BINDINGS" ]; then
	echo "PYTHON_CFLAGS=$PYTHON_CFLAGS" >> ./Makefile
	echo "PYTHON_LDFLAGS=$PYTHON_LDFLAGS" >> ./Makefile
	if [ "$BOOST_PYTHON_BINDINGS" ]; then 
		echo "BOOST_CFLAGS=$BOOST_CFLAGS" >> ./Makefile
		echo "BOOST_PYTHON_LDFLAGS=$BOOST_LDFLAGS $BOOST_PYTHON_LDFLAGS" >> ./Makefile
	else
		echo "PYTHON_CFLAGS+=$PYBIND_CFLAGS" >> ./Makefile
	fi
	echo "PYTHON_MODULEDIR=$PYTHON_MODULEDIR" >> ./Makefile
	echo "NUMPY_CFLAGS=$NUMPY_CFLAGS" >> ./Makefile
fi

if [ "$JULIA_BINDINGS" ]; then
	echo "JULIA_CFLAGS=$JULIA_CFLAGS" >> ./Makefile
	echo "JULIA_LDFLAGS=$JULIA_LDFLAGS" >> ./Makefile
	echo "CXX_JULIA_LDFLAGS=$CXX_JULIA_LDFLAGS" >> ./Makefile
	echo "CXX_JULIA_CFLAGS=$CXX_JULIA_CFLAGS" >> ./Makefile
	echo "JULIA_MODULEDIR=$JULIA_MODULEDIR" >> ./Makefile
fi

echo '

INCnuSQUIDS=$(PATH_nuSQUIDS)/include
LIBnuSQUIDS=$(PATH_nuSQUIDS)/lib

# FLAGS
CFLAGS= -O3 -fPIC -Ibuild -I$(INCnuSQUIDS) $(SQUIDS_CFLAGS) $(GSL_CFLAGS) $(HDF5_CFLAGS)
LDFLAGS= -Wl,-rpath -Wl,$(LIBnuSQUIDS) -L$(LIBnuSQUIDS)
LDFLAGS+= $(SQUIDS_LDFLAGS) $(GSL_LDFLAGS) $(HDF5_LDFLAGS) -lpthread
EXAMPLES_FLAGS=-I$(INCnuSQUIDS) $(CXXFLAGS) $(CFLAGS)

# Project files
NAME=nuSQuIDS
STAT_PRODUCT=lib$(NAME).a
DYN_PRODUCT_FULL_VER:=lib$(NAME)$(DYN_SUFFIX_FULL_VERSION)
DYN_PRODUCT_MAJ_VER:=lib$(NAME)$(DYN_SUFFIX_MAJOR_VERSION)
DYN_PRODUCT:=lib$(NAME)$(DYN_SUFFIX)
PYTHON_LIB:=$(NAME).so

# Compilation rules
all: $(LIBDIR)/$(STAT_PRODUCT) $(LIBDIR)/$(DYN_PRODUCT)

examples : $(EXAMPLES)

$(LIBDIR)/$(DYN_PRODUCT) : $(OBJECTS)
	@echo Linking $(DYN_PRODUCT)
	@rm -f "$(LIBDIR)/$(DYN_PRODUCT)" "$(LIBDIR)/$(DYN_PRODUCT_MAJ_VER)"
	@$(CXX) $(DYN_OPT) $(LDFLAGS) -o "$(LIBDIR)/$(DYN_PRODUCT_FULL_VER)" $(OBJECTS)
	@[ $$(uname -s) != Darwin ] || install_name_tool -id "$(DYN_PRODUCT_MAJ_VER)" "$(LIBDIR)/$(DYN_PRODUCT_FULL_VER)"
	@ln -s "$(DYN_PRODUCT_FULL_VER)" "$(LIBDIR)/$(DYN_PRODUCT_MAJ_VER)"
	@ln -s "$(DYN_PRODUCT_FULL_VER)" "$(LIBDIR)/$(DYN_PRODUCT)"

$(LIBDIR)/$(STAT_PRODUCT) : $(OBJECTS)
	@echo Linking $(STAT_PRODUCT)
	@$(AR) -rcs $(LIBDIR)/$(STAT_PRODUCT) $(OBJECTS)

build/%.o : src/%.cpp
	@echo Compiling $< to $@
	@$(CXX) $(CXXFLAGS) -c $(CFLAGS) $< -o $@

examples/Single_energy/single_energy : $(LIBDIR)/$(DYN_PRODUCT) examples/Single_energy/main.cpp
	@echo Compiling single energy example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Single_energy/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/Astrophysical_neutrino_flavor_ratio/astro_flv_ratio : $(LIBDIR)/$(DYN_PRODUCT) examples/Astrophysical_neutrino_flavor_ratio/main.cpp
	@echo Compiling astrophysical neutrino flavor ratio example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Astrophysical_neutrino_flavor_ratio/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/Multiple_energy/multiple_energy : $(LIBDIR)/$(DYN_PRODUCT) examples/Multiple_energy/main.cpp
	@echo Compiling multiple energy example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Multiple_energy/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/HDF5_Write_Read/write : $(LIBDIR)/$(DYN_PRODUCT) examples/HDF5_Write_Read/write.cpp
	@echo Compiling HDF5 write
	@$(CXX) $(EXAMPLES_FLAGS) examples/HDF5_Write_Read/write.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/HDF5_Write_Read/read : $(LIBDIR)/$(DYN_PRODUCT) examples/HDF5_Write_Read/read.cpp
	@echo Compiling HDF5 read
	@$(CXX) $(EXAMPLES_FLAGS) examples/HDF5_Write_Read/read.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/Atm_default/atm_default : $(LIBDIR)/$(DYN_PRODUCT) examples/Atm_default/main.cpp
	@echo Compiling atmospheric example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Atm_default/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

build/exBody.o : examples/Bodies/exBody.h examples/Bodies/exBody.cpp
	@$(CXX) $(EXAMPLES_FLAGS) -c examples/Bodies/exBody.cpp -o $@

build/ex_bodies_main.o : examples/Bodies/exBody.h examples/Bodies/main.cpp
	@$(CXX) $(EXAMPLES_FLAGS) -c examples/Bodies/main.cpp -o $@

examples/Bodies/bodies : $(LIBDIR)/$(DYN_PRODUCT) build/ex_bodies_main.o build/exBody.o
	@echo Compiling bodies example
	@$(CXX) $(EXAMPLES_FLAGS) build/ex_bodies_main.o build/exBody.o -lnuSQuIDS $(LDFLAGS) -o $@

build/exCross.o : examples/Xsections/exCross.h examples/Xsections/exCross.cpp
	@$(CXX) $(EXAMPLES_FLAGS) -c examples/Xsections/exCross.cpp -o $@

examples/Xsections/xsections : $(LIBDIR)/$(DYN_PRODUCT) examples/Xsections/main.cpp build/exCross.o
	@echo Compiling cross section example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Xsections/main.cpp build/exCross.o -lnuSQuIDS $(LDFLAGS) -o $@

build/nuSQUIDSDecoh.o : examples/Decoherence/nuSQUIDSDecoh.h examples/Decoherence/nuSQUIDSDecoh.cpp
	@$(CXX) $(EXAMPLES_FLAGS) -c examples/Decoherence/nuSQUIDSDecoh.cpp -o $@

examples/Decoherence/decoherence : $(LIBDIR)/$(DYN_PRODUCT) examples/Decoherence/main.cpp build/nuSQUIDSDecoh.o
	@echo Compiling decoherence example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Decoherence/main.cpp build/nuSQUIDSDecoh.o -lnuSQuIDS $(LDFLAGS) -o $@

examples/NSI/nsi : $(LIBDIR)/$(DYN_PRODUCT) examples/NSI/main.cpp
	@echo Compiling non-standard interaction example
	@$(CXX) $(EXAMPLES_FLAGS) examples/NSI/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/LV/lv : $(LIBDIR)/$(DYN_PRODUCT) examples/LV/main.cpp
	@echo Compiling Lorentz Violation example
	@$(CXX) $(EXAMPLES_FLAGS) examples/LV/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/Atm_BSM/atm_bsm: $(LIBDIR)/$(DYN_PRODUCT) examples/Atm_BSM/main.cpp
	@echo Compiling atmospheric with beyond standard model physics example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Atm_BSM/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

examples/Constant_density_layers/const_dens_layers : $(LIBDIR)/$(DYN_PRODUCT) examples/Constant_density_layers/main.cpp
	@echo Compiling constant density layer example
	@$(CXX) $(EXAMPLES_FLAGS) examples/Constant_density_layers/main.cpp -lnuSQuIDS $(LDFLAGS) -o $@

.PHONY: install uninstall clean test docs benchmark
clean:
	@echo Erasing generated files
	@rm -f $(PATH_nuSQUIDS)/build/*.o
	@rm -f $(LIBDIR)/*.a $(LIBDIR)/*.so $(LIBDIR)/*.dylib
	@rm -f benchmarks/benchmark

benchmarks/benchmark : $(LIBDIR)/$(DYN_PRODUCT) benchmarks/benchmark.cpp
	@echo Compiling benchmark suite
	@$(CXX) $(EXAMPLES_FLAGS) benchmarks/benchmark.cpp -lnuSQuIDS $(LDFLAGS) -o $@

benchmark : benchmarks/benchmark
	@echo Running nuSQuIDS benchmarks...
	@./benchmarks/benchmark

benchmark-quick : benchmarks/benchmark
	@echo "Running nuSQuIDS benchmarks (quick mode)..."
	@./benchmarks/benchmark --quick

doxygen:
	@mkdir -p ./docs
	@doxygen src/doxyfile
docs:
	@mkdir -p ./docs
	@doxygen src/doxyfile

test: $(LIBDIR)/$(DYN_PRODUCT) $(LIBDIR)/$(STAT_PRODUCT)
	@cd ./test ; ./run_tests

install: $(LIBDIR)/$(DYN_PRODUCT) $(LIBDIR)/$(STAT_PRODUCT)
	@echo Installing headers in $(PREFIX)/include/nuSQuIDS
	@mkdir -p "$(PREFIX)/include/nuSQuIDS"
	@cp "$(INCnuSQUIDS)"/nuSQuIDS/*.h "$(PREFIX)/include/nuSQuIDS"
	@echo Installing libraries in $(PREFIX)/$(INSTALL_LIBDIR)
	@mkdir -p "$(PREFIX)/$(INSTALL_LIBDIR)"
	@LC_ALL=C sed "'${REPLACE_INSTALL_FLAG}'" < "$(LIBDIR)/$(DYN_PRODUCT_FULL_VER)" | head -c $$(wc -c "$(LIBDIR)/$(DYN_PRODUCT_FULL_VER)" | awk '"'"'{print $$1}'"'"') /dev/stdin > "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_FULL_VER)"
	@LC_ALL=C sed "'${REPLACE_INSTALL_FLAG}'" < $(LIBDIR)/$(STAT_PRODUCT) | head -c $$(wc -c "$(LIBDIR)/$(STAT_PRODUCT)" | awk '"'"'{print $$1}'"'"') /dev/stdin > "$(PREFIX)/$(INSTALL_LIBDIR)/$(STAT_PRODUCT)"
	@[ $$(uname -s) != Darwin ] || install_name_tool -id "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_MAJ_VER)" "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_FULL_VER)"
	@rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT)" "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_MAJ_VER)"
	@ln -s "$(DYN_PRODUCT_FULL_VER)" "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_MAJ_VER)"
	@ln -s "$(DYN_PRODUCT_FULL_VER)" "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT)"
	@chmod 755 "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME)$(DYN_SUFFIX)" "$(PREFIX)/$(INSTALL_LIBDIR)/lib$(NAME).a" 
	@echo Installing config information in $(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig
	@mkdir -p "$(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig"
	@cp lib/nusquids.pc "$(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig"
	@echo Installing physics data in $(PREFIX)/share/nuSQuIDS
	@mkdir -p "$(PREFIX)/share/nuSQuIDS"
	@cp -r data/* "$(PREFIX)/share/nuSQuIDS/"
	@echo Installing nusquids-config in $(PREFIX)/$(INSTALL_BINDIR)
	@mkdir -p "$(PREFIX)/$(INSTALL_BINDIR)"
	@cp lib/nusquids-config "$(PREFIX)/$(INSTALL_BINDIR)/"
	@chmod 755 "$(PREFIX)/$(INSTALL_BINDIR)/nusquids-config"
' >> ./Makefile

if `pkg-config hdf5`; then
:
else
	echo '	@cp lib/hdf5.pc "$(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig"' >> ./Makefile
fi
echo '
uninstall:
	@echo Removing headers from $(PREFIX)/include/nuSQuIDS
	@rm -rf "$(PREFIX)/include/nuSQuIDS"
	@echo Removing libraries from $(PREFIX)/$(INSTALL_LIBDIR)
	@rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT)"
	@rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_MAJ_VER)"
	@rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_FULL_VER)"
	@rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/$(STAT_PRODUCT)"
	@echo Removing config information from $(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig
	@rm -f "$(PREFIX)/$(INSTALL_LIBDIR)/pkgconfig/nusquids.pc"
	@echo Removing nusquids-config from $(PREFIX)/$(INSTALL_BINDIR)
	@rm -f "$(PREFIX)/$(INSTALL_BINDIR)/nusquids-config"
' >> ./Makefile

if [ "$PYTHON_BINDINGS" ]; then
	echo '

python : $(LIBDIR)/$(PYTHON_LIB)
' >> ./Makefile

if [ "$BOOST_PYTHON_BINDINGS" ]; then 
	echo '
$(LIBDIR)/$(PYTHON_LIB) : build/nuSQUIDSpy.o $(LIBDIR)/$(STAT_PRODUCT)
	@echo Linking python bindings
	@$(CXX) $(DYN_OPT_PY) build/nuSQUIDSpy.o -Llib -l$(NAME) $(LDFLAGS) $(BOOST_PYTHON_LDFLAGS) $(PYTHON_LDFLAGS) -o $(LIBDIR)/$(PYTHON_LIB)

build/nuSQUIDSpy.o : resources/python/src_boostpython/nuSQUIDSpy.cpp
	@echo Compiling python bindings
	@$(CXX) $(CXXFLAGS) -c -Iresources/python/inc $(PYTHON_CFLAGS) $(BOOST_CFLAGS) $(NUMPY_CFLAGS) $(CFLAGS) $< -o $@
' >> ./Makefile
else
	echo '
$(LIBDIR)/$(PYTHON_LIB) : build/nuSQUIDSpy.o $(LIBDIR)/$(STAT_PRODUCT)
	@echo Linking python bindings
	@$(CXX) $(DYN_OPT_PY) build/nuSQUIDSpy.o -Llib -l$(NAME) $(LDFLAGS) $(PYTHON_LDFLAGS) -o $(LIBDIR)/$(PYTHON_LIB)

build/nuSQUIDSpy.o : resources/python/src_pybind/nuSQUIDSpy.cpp
	@echo Compiling python bindings
	@$(CXX) $(CXXFLAGS) -c $(PYTHON_CFLAGS) $(NUMPY_CFLAGS) $(CFLAGS) $< -o $@
' >> ./Makefile
fi
	echo '
python-install : $(LIBDIR)/$(PYTHON_LIB)
	@echo Installing python module in $(PYTHON_MODULEDIR)
	@mkdir -p $(PYTHON_MODULEDIR)
	@cp $(LIBDIR)/$(PYTHON_LIB) $(PYTHON_MODULEDIR)
	@[ $$(uname -s) != Darwin ] || install_name_tool -change $(DYN_PRODUCT_MAJ_VER) "$(PREFIX)/$(INSTALL_LIBDIR)/$(DYN_PRODUCT_MAJ_VER)" "$(PYTHON_MODULEDIR)/$(PYTHON_LIB)"

python-uninstall : $(LIBDIR)/$(PYTHON_LIB)
	@echo Removing python module from $(PYTHON_MODULEDIR)
	@rm $(PYTHON_MODULEDIR)/$(NAME).so

' >> ./Makefile
fi

if [ "$JULIA_BINDINGS" ]; then
	echo '

julia : $(JULIA_LIB)

$(JULIA_LIB) : build/nuSQUIDSjl.o $(STAT_PRODUCT)
	@echo Linking julia bindings
	@$(CXX) $(DYN_OPT_JL) build/nuSQUIDSjl.o -Llib -l$(NAME) $(LDFLAGS) $(CXX_JULIA_LDFLAGS) $(JULIA_LDFLAGS) -o $(JULIA_LIB)

build/nuSQUIDSjl.o : resources/julia/src/nuSQUIDSjl.cpp
	@echo Compiling juliabindings
	@$(CXX) $(CXXFLAGS) -c -Iresources/julia/inc $(JULIA_CFLAGS) $(CXX_JULIA_CFLAGS) $(CFLAGS) $< -o $@

julia-install : $(JULIA_LIB)
	@echo Installing julia module in $(JULIA_MODULEDIR)
	@mkdir -p $(JULIA_MODULEDIR)
	@cp $(JULIA_LIB) $(JULIA_MODULEDIR)

julia-uninstall : $(JULIAN_LIB)
	@echo Removing julia module from $(JULIA_MODULEDIR)
	@rm $(JULIA_MODULEDIR)/$(NAME).so

' >> ./Makefile
fi


echo "
export CXX=\"${CXX}\"
export CFLAGS=\"${CFLAGS} -I${SOURCE_PATH}/inlude ${SQUIDS_CFLAGS} ${GSL_CFLAGS} ${HDF5_CFLAGS}\"
export CXXFLAGS=\"${CXXFLAGS} -std=c++11\"
export LDFLAGS=\"${LDFLAGS} -L${SOURCE_PATH}/lib -Wl,-rpath -Wl,${SOURCE_PATH}/lib -lnuSQuIDS -lpthread ${SQUIDS_LDFLAGS} ${GSL_LDFLAGS} ${HDF5_LDFLAGS}\"
" > test/env_vars.sh
if uname | grep -q 'Darwin' ; then
	printf "export DYLD_LIBRARY_PATH=\"" >> test/env_vars.sh
	printf "${SOURCE_PATH}/lib:${SQUIDS_LIBDIR}:${GSL_LIBDIR}:${HDF5_LIBDIR}" >> test/env_vars.sh
	if [ "$DYLD_LIBRARY_PATH" ]; then
		printf ":${DYLD_LIBRARY_PATH}" >> test/env_vars.sh
	fi
else
	printf "export LD_LIBRARY_PATH=\"" >> test/env_vars.sh
	printf "${SOURCE_PATH}/lib:${SQUIDS_LIBDIR}:${GSL_LIBDIR}:${HDF5_LIBDIR}" >> test/env_vars.sh
	if [ "$LD_LIBRARY_PATH" ]; then
		printf ":${LD_LIBRARY_PATH}" >> test/env_vars.sh
	fi
fi
echo '"' >> test/env_vars.sh

echo "Done."
echo
echo "To build the library, run the following: make
After, to build examples: make examples"
if [ "$PYTHON_BINDINGS" ]; then
	echo "To build the python bindings run: make python"
	echo "To install the python bindings run: make python-install"
fi
