###############################################################################
# initialization
###############################################################################

# set some defaults if this is not being called from the main makefile
ifndef CALLED_FROM_MAIN

	# compilers
	CXX     := g++#      # C++ compiler
	JAVA    := java#     # Java virtual machine
	JAVAC   := javac#    # Java compiler
	JAVADOC := javadoc#  # Java documentation
	JAR     := jar#      # Java jar files

	# aliases
	MKDIR  := mkdir -p
	CP     := cp -rv
	MV     := mv -v
	RM     := rm -rfv

	# color definitions
	blue := $(shell tput setaf 6)
	sgr0 := $(shell tput sgr0)

	# detect os (linux, darwin)
	OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')

	# detect bit size
	UNAME_M := $(shell uname -m)
	ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 arm64 aarch64))
		ARCH := 64
	else
		ARCH := 32
	endif

	# declare the library file extension for your system
	ifeq ($(OS),darwin)
		# MacOS
		export LIBEXT_JAVA := jnilib
	else
		# linux
		export LIBEXT_JAVA := so
	endif

endif


################################################################################
# initialization
################################################################################

# The makefile will attempt to automatically find the /path/to/java/include
# where 'jni.h' resides. If there seems to be a problem detecting its location,
# you can either set the $JAVA_INC environment variable on your computer, or
# set it manually below.
#JAVA_INC := /usr/lib/jvm/default-java/include

# set JAVA_HOME, if it's unset or blank
ifeq ($(JAVA_HOME),)
	ifeq ($(OS),darwin)
		# MacOS
		JAVA_HOME := $(shell /usr/libexec/java_home 2>/dev/null)
	else
		# linux
		JAVA_HOME := $(shell $(JAVA) -XshowSettings:properties -version 2>&1 >/dev/null | grep "java.home" | cut -d"=" -f2 | tr -d '[:space:]')
	endif
endif

# try to find the java 'include' folder by looking for 'jni.h'
ifneq (,$(wildcard $(JAVA_INC)/jni.h))  # search the predefined $JAVA_INC
	# jni.h is in the predicted JAVA_INC, so do nothing

else ifneq (,$(wildcard $(JAVA_HOME)/include/jni.h))  # search $JAVA_HOME
	JAVA_INC := $(JAVA_HOME)/include

else ifneq (,$(wildcard $(JAVA_HOME)/../include/jni.h))  # search parent of $JAVA_HOME
	JAVA_INC := $(JAVA_HOME)/../include

else  # couldn't find jni.h
	JAVA_INC :=  # set JAVA_INC to blank. this will be checked later

endif

# exit with an error if we couldn't find jni.h
ifneq (,$(JAVA_HOME))
ifeq (,$(JAVA_INC))
$(error "Couldn't find 'jni.h'. Please export 'JAVA_INC' or define it at the top of the /rstt/SLBM_JNI/Makefile.")
endif
endif


################################################################################
# compilation parameters
################################################################################

# define output file
OUT := libslbmjni.$(LIBEXT_JAVA)
OUTJAR := slbmjni.jar
OUTDIR := ../lib

# includes
INC := -Icc/include -I../GeoTessCPP/include -I../SLBM/include -I$(JAVA_INC) -I$(JAVA_INC)/$(OS)

# libraries
LIBS := -L$(OUTDIR) -lgeotesscpp -lslbm

# compiling parameters
ifeq ($(UNAME_M),$(filter $(UNAME_M),arm64 aarch64))
	CXXFLAGS := -mcpu=native
else
	CXXFLAGS := -march=native -m$(ARCH)
endif
CXXFLAGS += -D$(OS) -O1 -fPIC -std=c++11

# specific LD_FLAGS on Mac
ifeq ($(OS),darwin)

	# if Xcode version is >= 15, we need to add -Wl,-ld_classic to the linker
	# see: https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#Linking
	XCODE_VERSION := $(shell ld -version_details | grep 'LLVM' | grep -oE '[0-9\.]+' | cut -d '.' -f 1)
	ifeq ($(shell expr $(XCODE_VERSION) \>= 15), 1)
		OTHER_LDFLAGS += -Wl,-ld_classic
	endif

	# if using clang instead of gnu compiler, set additional flags
	CLANG := $(shell $(CXX) -v 2>&1 | grep -qi clang; echo $$?)
	ifeq ($(CLANG),0)
		CXXFLAGS += -Wno-deprecated-declarations
		OTHER_LDFLAGS += -undefined dynamic_lookup -rpath @loader_path
	endif

endif

# list of objects to compile
OBJS = cc/src/pglJavaUtil.o cc/src/SlbmInterfaceJNI.o


################################################################################
# recipes
################################################################################

# recipe to make everything and run tests
all: initialize slbmjni slbmjnijar finalize

# command that tells us which recipes don't build source files
.PHONY: tmp all initialize msg_intro slbmjni slbmjnijar msg_docs docs finalize clean cleanall

# initialize compilation script
initialize: msg_intro

# print intro message
msg_intro:
	@echo "$(blue)------------------------------------------------------------$(sgr0)"
	@echo "$(blue)Making RSTT JNI library...$(sgr0)"
	@echo "$(blue)------------------------------------------------------------$(sgr0)"


# to build any *.o file, compile its corresponding *.cc file
%.o: %.cc
	@printf "JAVA_HOME=%s    JAVA_INC=%s\n" $(JAVA_HOME) $(JAVA_INC)
	@printf "$(blue)(Building obj) $(sgr0)"
	$(CXX) $(CXXFLAGS) $(INC) -o $@ -c $<


# build library after building each prerequisite in $(OBJS)
slbmjni: initialize $(OUT)

# MacOS
ifeq ($(OS),darwin)
$(OUT): $(OBJS)
	@printf "$(blue)(Building lib) $(sgr0)"
	$(CXX) $(CXXFLAGS) -dynamiclib $(OTHER_LDFLAGS) -install_name @rpath/$(OUT) -o $(OUT) $(OBJS) $(LIBS)

# linux
else
$(OUT): $(OBJS)
	@printf "$(blue)(Building lib) $(sgr0)"
	$(CXX) $(CXXFLAGS) -shared -Wl,-rpath,'$$ORIGIN' -o $(OUT) $(OBJS) $(LIBS)

endif


# build jar
slbmjnijar: java/SlbmInterface/build slbmjni
	@printf "$(blue)(Compiling java) $(sgr0)"
	$(JAVAC) -cp java/SlbmInterface/src/gov/sandia/gnem/slbmjni -d java/SlbmInterface/build java/SlbmInterface/src/gov/sandia/gnem/slbmjni/*.java
	@printf "$(blue)(Building jar) $(sgr0)"
	$(JAR) -cf $(OUTJAR) -C java/SlbmInterface/build gov/sandia/gnem/slbmjni

java/SlbmInterface/build:
	@printf "$(blue)(Make directory) $(sgr0)"
	$(MKDIR) java/SlbmInterface/build


# print docs msg
msg_docs:
	@echo "$(blue)------------------------------------------------------------$(sgr0)"
	@echo "$(blue)Making RSTT JNI documentation...$(sgr0)"
	@echo "$(blue)------------------------------------------------------------$(sgr0)"

# documentation
docs: msg_docs java/SlbmInterface/doc
java/SlbmInterface/doc:
ifeq (, $(shell which $(JAVADOC)))  # javadoc is not installed
	@printf "$(blue)(Building HTML docs) $(sgr0)"
	@echo "$(JAVADOC) is not installed. Skipping..."

else  # javadoc is installed
	@printf "$(blue)(Building HTML docs) $(sgr0)"
	cd java/SlbmInterface; $(JAVADOC) -d doc -private -windowtitle "RSTT Documentation - Java" src/gov/sandia/gnem/slbmjni/*.java
	$(CP) ../.docs/javadoc/doc/ java/SlbmInterface/doc/

endif


# move files and clean up
finalize:
	@printf "$(blue)(Moving files) $(sgr0)"
	$(MV) $(OUT) $(OUTJAR) $(OUTDIR)

clean:
	@printf "$(blue)(Clean *.o) $(sgr0)"
	$(RM) cc/src/*.o
	@printf "$(blue)(Clean *.class) $(sgr0)"
	$(RM) java/SlbmInterface/build

cleanall: clean
	@printf "$(blue)(Clean docs) $(sgr0)"
	$(RM) java/SlbmInterface/doc
	@printf "$(blue)(Clean libs) $(sgr0)"
	$(RM) $(OUTDIR)/$(OUT) $(OUTDIR)/$(OUT)
