# Source Code for raknet
file(
	GLOB SOURCES_RAKNET
	LIST_DIRECTORIES false
	RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
	${CMAKE_CURRENT_SOURCE_DIR}/raknet/Source/*.cpp
)

# Source Code for recast
file(
	GLOB SOURCES_RECAST
	LIST_DIRECTORIES false
	RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
	${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Recast/Source/*.cpp
)

# Source Code for detour
file(
	GLOB SOURCES_DETOUR
	LIST_DIRECTORIES false
	RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
	${CMAKE_CURRENT_SOURCE_DIR}/recastnavigation/Detour/Source/*.cpp
)

# Source Code for tinyxml2
file(
	GLOB SOURCES_TINYXML2
	LIST_DIRECTORIES false
	RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
	${CMAKE_CURRENT_SOURCE_DIR}/tinyxml2/tinyxml2.cpp
)

# Source Code for libbcrypt
file(
	GLOB SOURCES_LIBBCRYPT
	LIST_DIRECTORIES false
	RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
	${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/*.c
	${CMAKE_CURRENT_SOURCE_DIR}/libbcrypt/src/*.c
)

file(
	GLOB SOURCES_SQLITE3
	LIST_DIRECTORIES false
	RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
	${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.cpp
	${CMAKE_CURRENT_SOURCE_DIR}/SQLite/*.c
)

# mariadb connector cpp
# On Windows ClangCL can't compile the connector from source but can link to an msvc compiled one,
# so prefer the prebuilt binaries unless MARIADB_BUILD_SOURCE is specified
if(WIN32 AND NOT MARIADB_BUILD_SOURCE)
	set(MARIADB_MSI_DIR "${PROJECT_BINARY_DIR}/msi")
	set(MARIADB_CONNECTOR_DIR "${PROJECT_BINARY_DIR}/mariadbcpp")
	set(MARIADB_C_CONNECTOR_DIR "${MARIADB_CONNECTOR_DIR}/MariaDB/MariaDB Connector C 64-bit")
	set(MARIADB_CPP_CONNECTOR_DIR "${MARIADB_CONNECTOR_DIR}/MariaDB/MariaDB C++ Connector 64-bit")

	file(MAKE_DIRECTORY "${MARIADB_MSI_DIR}")
	file(MAKE_DIRECTORY "${MARIADB_CONNECTOR_DIR}")

	if(NOT EXISTS "${MARIADB_MSI_DIR}/mariadb-connector-c-3.2.5-win64.msi" )
		message("Downloading mariadb connector/c")
		file(DOWNLOAD https://dlm.mariadb.com/1936366/connectors/c/connector-c-3.2.5/mariadb-connector-c-3.2.5-win64.msi
			"${MARIADB_MSI_DIR}/mariadb-connector-c-3.2.5-win64.msi"
			EXPECTED_HASH MD5=09d418c290109068a5bea136dafca36b)
	endif()

	if(NOT EXISTS "${MARIADB_MSI_DIR}/mariadb-connector-cpp-1.0.1-win64.msi" )
		message("Downloading mariadb connector/c++")
		file(DOWNLOAD https://dlm.mariadb.com/1683453/connectors/cpp/connector-cpp-1.0.1/mariadb-connector-cpp-1.0.1-win64.msi
			"${MARIADB_MSI_DIR}/mariadb-connector-cpp-1.0.1-win64.msi"
			EXPECTED_HASH MD5=548e743fbf067d21d42b81d958bf4ed7)
	endif()


	file(TO_NATIVE_PATH "${MARIADB_CONNECTOR_DIR}" MSIEXEC_TARGETDIR)
	# extract msi files without installing to users system
	if(NOT EXISTS "${MARIADB_C_CONNECTOR_DIR}")
		file(TO_NATIVE_PATH "${MARIADB_MSI_DIR}/mariadb-connector-c-3.2.5-win64.msi" MSI_DIR)
		execute_process(COMMAND msiexec /a ${MSI_DIR} /qn TARGETDIR=${MSIEXEC_TARGETDIR})
	endif()
	
	if(NOT EXISTS "${MARIADB_CPP_CONNECTOR_DIR}")
	file(TO_NATIVE_PATH "${MARIADB_MSI_DIR}/mariadb-connector-cpp-1.0.1-win64.msi" MSI_DIR)
		execute_process(COMMAND msiexec /a ${MSI_DIR} /qn TARGETDIR=${MSIEXEC_TARGETDIR})
	endif()
	
	set(MARIADB_SHARED_LIBRARY_LOCATION "${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.dll")
	set(MARIADB_IMPLIB_LOCATION "${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.lib")
	set(MARIADB_INCLUDE_DIR "${MARIADB_CPP_CONNECTOR_DIR}/include/mariadb")

	add_custom_target(mariadb_connector_cpp)
	add_custom_command(TARGET mariadb_connector_cpp POST_BUILD
					COMMAND ${CMAKE_COMMAND} -E copy_if_different 
					"${MARIADB_CPP_CONNECTOR_DIR}/mariadbcpp.dll"
					"${MARIADB_C_CONNECTOR_DIR}/lib/libmariadb.dll"
					"${PROJECT_BINARY_DIR}")

	# MariaDB uses plugins that the database needs to load, the prebuilt binaries by default will try to find the libraries in system directories,
	# so set this define and the servers will set the MARIADB_PLUGIN_DIR environment variable to the appropriate directory.
	# Plugin directory is determined at dll load time (this will happen before main()) so we need to delay the dll load so that we can set the environment variable
	add_link_options(/DELAYLOAD:${MARIADB_SHARED_LIBRARY_LOCATION})
	add_compile_definitions(MARIADB_PLUGIN_DIR_OVERRIDE="${MARIADB_CPP_CONNECTOR_DIR}/plugin")
else() # Build from source

	include(ExternalProject)
	if(WIN32)
		set(MARIADB_EXTRA_COMPILE_FLAGS /EHsc)
		set(MARIADB_EXTRA_CMAKE_ARGS -DWITH_MSI=OFF)
	elseif(APPLE)
		set(MARIADB_EXTRA_COMPILE_FLAGS -D_GLIBCXX_USE_CXX11_ABI=0)
		set(MARIADB_EXTRA_CMAKE_ARGS -DWITH_EXTERNAL_ZLIB=ON -DOPENSSL_ROOT_DIR=${OPENSSL_ROOT_DIR})
	else()
		set(MARIADB_EXTRA_COMPILE_FLAGS -D_GLIBCXX_USE_CXX11_ABI=0)
	endif()
	
	ExternalProject_Add(mariadb_connector_cpp
						SOURCE_DIR ${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp
						CMAKE_ARGS "-DCMAKE_CXX_FLAGS:STRING= ${MARIADB_EXTRA_COMPILE_FLAGS}"
									-DCMAKE_BUILD_RPATH_USE_ORIGIN=${CMAKE_BUILD_RPATH_USE_ORIGIN}
									-DCMAKE_INSTALL_PREFIX=./mariadbcpp # Points the connector to the correct plugin directory
									-DINSTALL_PLUGINDIR=plugin
									${MARIADB_EXTRA_CMAKE_ARGS}
						PREFIX "${PROJECT_BINARY_DIR}/mariadbcpp"
						BUILD_COMMAND cmake --build . --config RelWithDebInfo -j${__maria_db_connector_compile_jobs__}
						INSTALL_COMMAND "")

	ExternalProject_Get_Property(mariadb_connector_cpp BINARY_DIR)

	if(WIN32)
		set(MARIADB_SHARED_LIBRARY_NAME mariadbcpp.dll)
		set(MARIADB_PLUGIN_SUFFIX .dll)
		set(MARIADB_IMPLIB_LOCATION "${BINARY_DIR}/RelWithDebInfo/mariadbcpp.lib")
		
		# When built from source windows only seems to check same folder as exe instead specified folder, so use
		# environment variable to force it
		add_link_options(/DELAYLOAD:mariadbcpp.dll)
		add_compile_definitions(MARIADB_PLUGIN_DIR_OVERRIDE="${PROJECT_BINARY_DIR}/mariadbcpp/plugin")
	else()
		set(MARIADB_SHARED_LIBRARY_NAME libmariadbcpp${CMAKE_SHARED_LIBRARY_SUFFIX})
		set(MARIADB_PLUGIN_SUFFIX .so)
	endif()

	get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
	if(isMultiConfig)
		set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/RelWithDebInfo/${MARIADB_SHARED_LIBRARY_NAME}")
		set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}/$<CONFIG>")
		set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb/RelWithDebInfo")
	else()
		set(MARIADB_SHARED_LIBRARY_LOCATION "${BINARY_DIR}/${MARIADB_SHARED_LIBRARY_NAME}")
		set(MARIADB_SHARED_LIBRARY_COPY_LOCATION "${PROJECT_BINARY_DIR}")
		set(MARIADB_PLUGINS_LOCATION "${BINARY_DIR}/libmariadb")
	endif()

	set(MARIADB_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/include/")

	add_custom_command(TARGET mariadb_connector_cpp POST_BUILD
						COMMAND ${CMAKE_COMMAND} -E make_directory
						${BINARY_DIR}/mariadbcpp/plugin
						${MARIADB_SHARED_LIBRARY_COPY_LOCATION}
						
						COMMAND ${CMAKE_COMMAND} -E copy_if_different 
						${MARIADB_SHARED_LIBRARY_LOCATION}
						${MARIADB_SHARED_LIBRARY_COPY_LOCATION}

						COMMAND ${CMAKE_COMMAND} -E copy_if_different
						${MARIADB_PLUGINS_LOCATION}/caching_sha2_password${MARIADB_PLUGIN_SUFFIX}
						${MARIADB_PLUGINS_LOCATION}/client_ed25519${MARIADB_PLUGIN_SUFFIX}
						${MARIADB_PLUGINS_LOCATION}/dialog${MARIADB_PLUGIN_SUFFIX}
						${MARIADB_PLUGINS_LOCATION}/mysql_clear_password${MARIADB_PLUGIN_SUFFIX}
						${MARIADB_PLUGINS_LOCATION}/sha256_password${MARIADB_PLUGIN_SUFFIX}
						${BINARY_DIR}/mariadbcpp/plugin)
endif()

# Remove the CMakeLists.txt file from the tests folder for the maria-db-connector so we dont compile the tests.
if(EXISTS "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists.txt")
	file(REMOVE "${CMAKE_SOURCE_DIR}/thirdparty/mariadb-connector-cpp/test/CMakeLists.txt")
endif()

# Create mariadb connector library object
add_library(mariadbConnCpp SHARED IMPORTED GLOBAL)
set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_LOCATION ${MARIADB_SHARED_LIBRARY_LOCATION})

if(WIN32)
	set_property(TARGET mariadbConnCpp PROPERTY IMPORTED_IMPLIB ${MARIADB_IMPLIB_LOCATION})
endif()

# Add directories to include lists
target_include_directories(mariadbConnCpp INTERFACE ${MARIADB_INCLUDE_DIR})
add_dependencies(mariadbConnCpp mariadb_connector_cpp)

# Create our third party library objects
add_library(raknet ${SOURCES_RAKNET})
add_library(tinyxml2 ${SOURCES_TINYXML2})
add_library(detour ${SOURCES_DETOUR})
add_library(recast ${SOURCES_RECAST})
add_library(libbcrypt ${SOURCES_LIBBCRYPT})
add_library(sqlite3 ${SOURCES_SQLITE3})

if(WIN32)
	# Link Win Sockets 2 to RakNet
	target_link_libraries(raknet ws2_32)
elseif(UNIX)
	# Add warning disable flags and link Unix libraries to sqlite3
	target_link_libraries(sqlite3 pthread dl m)

	#  -Wno-unused-result -Wno-unknown-pragmas -fpermissive
	target_compile_options(sqlite3 PRIVATE "-Wno-return-local-addr" "-Wno-maybe-uninitialized")
	target_compile_options(raknet PRIVATE "-Wno-write-strings" "-Wformat-overflow=0" "-Wformat=0")
	target_compile_options(libbcrypt PRIVATE "-Wno-implicit-function-declaration" "-Wno-int-conversion")
endif()

# Download Backtrace if configured
if(UNIX AND NOT APPLE)
	include(FetchContent)
	if (__include_backtrace__ AND __compile_backtrace__)
		FetchContent_Declare(
			backtrace
			GIT_REPOSITORY https://github.com/ianlancetaylor/libbacktrace.git
		)

		FetchContent_MakeAvailable(backtrace)

		if (NOT EXISTS ${backtrace_SOURCE_DIR}/.libs)
			set(backtrace_make_cmd "${backtrace_SOURCE_DIR}/configure --prefix=\"/usr\" --enable-shared --with-system-libunwind")

			execute_process(
				COMMAND bash -c "cd ${backtrace_SOURCE_DIR} && ${backtrace_make_cmd} && make && cd ${CMAKE_SOURCE_DIR}"
			)
		endif()

		link_directories(${backtrace_SOURCE_DIR}/.libs/)
		include_directories(${backtrace_SOURCE_DIR})
	endif()
endif()