# Require the latest CMake version.
cmake_minimum_required(VERSION 4.2.1)

project(archipelago)

# ExternalContent, the better FetchContent and ExternalProject. Even beats CPM because it isn't written to be fancy!
include(cmake/externalcontent/ExternalContent.cmake)

#--------------------------------------------------------------------------------#
# Options
#--------------------------------------------------------------------------------#

set(CACHE{ENABLE_SSL} TYPE BOOL HELP "Enable SSL support via wolfSSL?" VALUE ON)
set(CACHE{ENABLE_COMPRESSION} TYPE BOOL HELP "Enable support for compression?" VALUE ON)

#--------------------------------------------------------------------------------#
# Libraries
#--------------------------------------------------------------------------------#

if(TRUE) # Database support
	## PostGreSQL
	# Depends on massive mono-repo project that we don't have the time to investigate now.
	find_package("libpqxx" OPTIONAL)

	## MariaDB
	# Depends on massive mono-repo project that we don't have the time to investigate now.
	find_package("libmariadb" OPTIONAL)
endif()

if(TRUE) # ASIO (Standalone)
	ExternalContent(
		NAME "asio"
		DOWNLOAD_URL "https://altushost-swe.dl.sourceforge.net/project/asio/asio/1.36.0%20%28Stable%29/asio-1.36.0.zip?viasf=1"
		DOWNLOAD_FILE "asio-1.36.0.zip"
		DOWNLOAD_HASH "SHA512;6D867F6C63BC259110E00726D0DD38090F5E55EE01EEFF94A3590B1351967FD7E19EE8F7601A197723FA072CEA8F29D00A7C60A8E97D441CE3D931EE1A098F06"
		SKIP_CONFIGURE
		SKIP_BUILD
		SKIP_INSTALL
	)
	if(NOT TARGET asio)
		add_library("asio" INTERFACE)
		file(GLOB_RECURSE _FILES FOLLOW_SYMLINKS CONFIGURE_DEPENDS "${asio_SOURCE_PATH}/include/*")
		source_group(TREE "${asio_SOURCE_PATH}/include" PREFIX "" FILES ${_FILES})
		target_sources("asio"
			PRIVATE ${_FILES}
		)
		target_include_directories("asio"
			INTERFACE "${asio_SOURCE_PATH}/include"
		)
	endif()
	if(NOT TARGET boost::asio)
		add_library("boost::asio" ALIAS "asio")
	endif()
endif()

if(TRUE) # nlohmann's JSON
	ExternalContent(
		NAME "nlohmann_json"
		GIT_URL "https://github.com/nlohmann/json.git"
		GIT_REF "v3.12.0"
		GIT_CLONE_OPTIONS --depth 1 --no-single-branch --recurse-submodules
		GIT_CHECKOUT_OPTIONS --recurse-submodules
		CONFIGURE_OPTIONS -D JSON_BuildTests:BOOL=OFF -D JSON_CI:BOOL=OFF -D JSON_MultipleHeaders:BOOL=OFF
		SKIP_BUILD
	)
	find_package("nlohmann_json" REQUIRED CONFIG
		PATHS "${nlohmann_json_INSTALL_PATH}"
	)
endif()

if(TRUE) # badaix's JSONRPC++
	#!TODO: Replace with our own, this implementation isn't compliant with C++ standards at all.

	function(jsonrpcpp_patch)
		if(EXTERNALCONTENT_DOWNLOAD_DIRTY)
			file(GLOB_RECURSE _PATCHES FOLLOW_SYMLINKS CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/patches/badaix-jsonrpcpp/*")
			execute_process(
				COMMAND "git" "apply" "${_PATCHES}"
				WORKING_DIRECTORY "${EXTERNALCONTENT_SOURCE_PATH}"
				COMMAND_ECHO STDOUT
			)
			set(_EC_PATCH_DIRTY ON)
		endif()
	endfunction()

	ExternalContent(
		NAME "jsonrpcpp"
		GIT_URL "https://github.com/badaix/jsonrpcpp.git"
		GIT_REF "v1.4.0"
		GIT_CLONE_OPTIONS --depth 1 --no-single-branch --recurse-submodules
		GIT_CHECKOUT_OPTIONS --recurse-submodules
		PATCH_FUNCTION jsonrpcpp_patch
		CONFIGURE_ARGS -D BUILD_EXAMPLE:BOOL=OFF -D BUILD_TESTS:BOOL=OFF -D CATCH_INSTALL_DOCS:BOOL=OFF -D CATCH_INSTALL_EXTRAS:BOOL=ON
		BUILD_ARGS --parallel --config Release --clean-first
	)

	# This doesn't have a proper CMake module yet.
	if(NOT TARGET jsonrpcpp)
		add_library("jsonrpcpp" INTERFACE)
		file(GLOB_RECURSE _FILES FOLLOW_SYMLINKS CONFIGURE_DEPENDS "${jsonrpcpp_SOURCE_PATH}/include/*")
		source_group(TREE "${jsonrpcpp_SOURCE_PATH}/include" PREFIX "" FILES ${_FILES})
		target_sources("jsonrpcpp"
			PRIVATE ${_FILES}
		)
		target_include_directories("jsonrpcpp"
			INTERFACE "${jsonrpcpp_INSTALL_PATH}/include"
		)
		target_link_libraries("jsonrpcpp"
			INTERFACE "nlohmann_json::nlohmann_json"
		)
	endif()
	if(NOT TARGET badaix::jsonrpcpp)
		add_library("badaix::jsonrpcpp" ALIAS "jsonrpcpp")
	endif()
endif()

if(TRUE) # WebSocket++
	ExternalContent(
		NAME "websocketpp"
		GIT_URL "https://github.com/xaymar/websocketpp.git"
		GIT_REF "patch-modern-cpp-and-asio"
		GIT_CLONE_OPTIONS --depth 1 --no-single-branch --recurse-submodules
		GIT_CHECKOUT_OPTIONS --recurse-submodules
		CONFIGURE_ARGS -D ENABLE_CPP11:BOOL=ON -D BUILD_EXAMPLES:BOOL=OFF -D BUILD_TESTS:BOOL=OFF -D USE_ASIO_STANDALONE:BOOL=ON
		BUILD_ARGS --parallel --config Release
	)
	find_package("websocketpp" REQUIRED CONFIG
		PATHS "${websocketpp_INSTALL_PATH}"
	)
endif()

if(ENABLE_SSL) # wolfssl
	ExternalContent(
		NAME "wolfssl"
		GIT_URL "https://github.com/wolfSSL/wolfssl.git"
		GIT_REF "v5.8.4-stable"
		GIT_CLONE_OPTIONS --depth 1 --no-single-branch --recurse-submodules
		GIT_CHECKOUT_OPTIONS --recurse-submodules
		CONFIGURE_ARGS -D BUILD_SHARED_LIBS:BOOL=OFF -D CMAKE_BUILD_TYPE:STRING=RelWithDebInfo -D WOLFSSL_CRYPT_TESTS:BOOL=OFF -D WOLFSSL_EXAMPLES:BOOL=OFF
		BUILD_ARGS --parallel --config Release --clean-first
	)
	find_package("wolfssl" REQUIRED CONFIG
		PATHS "${wolfssl_INSTALL_PATH}"
	)
endif()

if(ENABLE_COMPRESSION) # Compression support
	# zlib-ng - zlib, but for modern systems
	ExternalContent(
		NAME "zlib-ng"
		GIT_URL "https://github.com/zlib-ng/zlib-ng.git"
		GIT_REF "2.3.2"
		GIT_CLONE_OPTIONS --depth 1 --no-single-branch --recurse-submodules
		GIT_CHECKOUT_OPTIONS --recurse-submodules
		CONFIGURE_ARGS -D BUILD_SHARED_LIBS:BOOL=OFF -D CMAKE_C_STANDARD:STRING=17 -D BUILD_TESTING:BOOL=OFF -D WITH_GTEST:BOOL=OFF -D WITH_FUZZERS:BOOL=OFF -D WITH_BENCHMARKS:BOOL=OFF -D WITH_BENCHMARK_APPS:BOOL=OFF -D INSTALL_UTILS:BOOL=OFF
		BUILD_ARGS --parallel --config Release --clean-first
	)
	find_package("zlib-ng" REQUIRED CONFIG
		PATHS "${zlib-ng_INSTALL_PATH}"
	)
endif()

#--------------------------------------------------------------------------------#
# Project
#--------------------------------------------------------------------------------#

file(GLOB_RECURSE _INCLUDE FOLLOW_SYMLINKS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/pub/*")
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/pub" PREFIX "Public" FILES ${_INCLUDE})

file(GLOB_RECURSE _SOURCE FOLLOW_SYMLINKS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/priv/*")
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/priv" PREFIX "Private" FILES ${_SOURCE})

add_executable("room-server")

target_sources("room-server"
	PRIVATE
		${_SOURCE}
	PUBLIC
		${_INCLUDE}
)

target_include_directories("room-server"
	PRIVATE
		"priv"
		"pub/apsr"
	PUBLIC
		"pub"
)

target_link_libraries("room-server"
	PRIVATE
		wolfSSL
		nlohmann_json::nlohmann_json
		badaix::jsonrpcpp
		websocketpp::websocketpp
		zlib-ng::zlib
)

set_target_properties("room-server" PROPERTIES
	# Always generate position independent code.
	POSITION_INDEPENDENT_CODE ON

	# Set C++ Standard and Extensions
	C_STANDARD 17
	C_STANDARD_REQUIRED ON
	CXX_STANDARD 20
	CXX_STANDARD_REQUIRED ON
	CXX_EXTENSIONS OFF

	# Remove prefix from generated files.
	PREFIX ""
	IMPORT_PREFIX ""

	# Never treat warnings as errors.
	COMPILE_WARNING_AS_ERROR OFF
)

if(WIN32)
	# Disable/Enable a ton of things.
	target_compile_definitions("room-server" PRIVATE
		# Microsoft Visual C++
		_CRT_SECURE_NO_WARNINGS
		_ENABLE_EXTENDED_ALIGNED_STORAGE

		# Windows version target
		_WIN32_WINNT=0x0A00
	)
endif()
