cmake_minimum_required(VERSION 3.10)
project(psemek)

cmake_policy(SET CMP0077 NEW)

set(CMAKE_CXX_STANDARD 20)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")

string(TOUPPER "${CMAKE_BUILD_TYPE}" PSEMEK_BUILD_TYPE)

set(_PSEMEK_ALL_PLATFORMS linux windows mac android web)

if(WIN32)
	set(_PSEMEK_PLATFORM windows)
elseif(APPLE)
	set(_PSEMEK_PLATFORM mac)
elseif(ANDROID)
	set(_PSEMEK_PLATFORM android)
elseif(UNIX)
	if (CMAKE_SYSTEM_NAME STREQUAL Emscripten)
		set(_PSEMEK_PLATFORM web)
	else()
		set(_PSEMEK_PLATFORM linux)
	endif()
else()
	message(WARNING "Failed to detect platform")
	set(_PSEMEK_PLATFORM unknown)
endif()

set(PSEMEK_PLATFORM "${_PSEMEK_PLATFORM}" CACHE INTERNAL "Build platform (auto-detected)")

foreach(_PLATFORM IN LISTS _PSEMEK_ALL_PLATFORMS)
	string(TOUPPER "${_PLATFORM}" _PLATFORM_UPPER)
	set(_PLATFORM_ON OFF)
	if("${_PLATFORM}" STREQUAL "${_PSEMEK_PLATFORM}")
		set(_PLATFORM_ON ON)
	endif()
	set(PSEMEK_PLATFORM_${_PLATFORM_UPPER} "${_PLATFORM_ON}" CACHE INTERNAL "Build platform is ${_PLATFORM}")
endforeach()

set(PSEMEK_DEFINITIONS)
if(PSEMEK_BUILD_TYPE STREQUAL "DEBUG")
	list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_DEBUG=1")
endif()

option(PSEMEK_ROBUST_PREDICATES "Turn on robust geometric predicates" OFF)
if(PSEMEK_ROBUST_PREDICATES)
	list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_ROBUST_PREDICATES=1")
endif()

option(PSEMEK_USE_FREETYPE "Include Freetype fonts support" OFF)
if(PSEMEK_USE_FREETYPE)
	list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_USE_FREETYPE=1")
endif()

set(PSEMEK_CXX_FLAGS)
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"))
	list(APPEND PSEMEK_CXX_FLAGS -Wall -Werror -Wextra -pedantic -Wno-narrowing -Wno-sign-compare)
endif()
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
	# gcc gives way too many false positives on -Wmaybe-uninitialized
	list(APPEND PSEMEK_CXX_FLAGS -Wno-maybe-uninitialized)
	if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13)
		# gcc-13 gives false positive -Wdangling-reference in ecs::accessor::get()
		list(APPEND PSEMEK_CXX_FLAGS -Wno-dangling-reference)
	endif()
endif()
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang"))
	# -Wdtor-name gives false-positive on audio::engine::impl::~impl
	list(APPEND PSEMEK_CXX_FLAGS -Wno-dtor-name)
endif()

set(PSEMEK_BACKEND "SDL2" CACHE STRING "Application backend (OFF/SDL2/ANDROID)")
option(PSEMEK_LEGACY_UI "Use legacy UI library" OFF)

message(STATUS "Using backend ${PSEMEK_BACKEND}")

if(PSEMEK_BACKEND STREQUAL "ANDROID")
	set(PSEMEK_GL_API gles32)
	set(PSEMEK_GL_LIBRARIES GLESv3 EGL)
	set(PSEMEK_PACKAGE_AS_LIBRARY ON CACHE INTERNAL "Build applications as shared libraries")
	list(APPEND PSEMEK_CXX_FLAGS -fPIC)
elseif(CMAKE_SYSTEM_NAME STREQUAL Emscripten)
	set(PSEMEK_GL_API gles30-emscripten)
	set(PSEMEK_GL_LIBRARIES EGL)
	set(PSEMEK_PACKAGE_AS_LIBRARY OFF CACHE INTERNAL "Build applications as shared libraries")
	list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_GLES=1")
	list(APPEND PSEMEK_CXX_FLAGS -sUSE_SDL=2 -fexperimental-library)
	# by default emcc doesn't produce catch clauses, but psemek is designed around exceptions
	list(APPEND PSEMEK_CXX_FLAGS -sDISABLE_EXCEPTION_CATCHING=0)
	if(CMAKE_BUILD_TYPE STREQUAL Debug)
		list(APPEND PSEMEK_CXX_FLAGS -g)
	endif()
else()
	find_package(Threads REQUIRED)
	set(OpenGL_GL_PREFERENCE LEGACY)
	find_package(OpenGL REQUIRED)
	set(PSEMEK_GL_API gl33)
	set(PSEMEK_GL_LIBRARIES OpenGL::GL)
	set(PSEMEK_PACKAGE_AS_LIBRARY OFF CACHE INTERNAL "Build applications as shared libraries")
endif()

if(NOT DEFINED PSEMEK_GRAPHICS_API)
	set(PSEMEK_GRAPHICS_API OPENGL)
endif()

if(PSEMEK_GRAPHICS_API STREQUAL WEBGPU)
	find_package(wgpu-native 29.0.1.1 EXACT REQUIRED)
endif()

message(STATUS "Using graphics API ${PSEMEK_GRAPHICS_API}")
list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_GRAPHICS_API_${PSEMEK_GRAPHICS_API}=1")

option(PSEMEK_STACKTRACE "Use Boost.Stacktrace for stacktraces in exceptions" ON)

if(PSEMEK_STACKTRACE)
	list(APPEND PSEMEK_DEFINITIONS "-DPSEMEK_STACKTRACE=1")
endif()

add_subdirectory(3rdparty)

get_directory_property(PSEMEK_PARENT_DIRECTORY PARENT_DIRECTORY)

add_subdirectory(package)

if(PSEMEK_PACKAGE_MODE AND PSEMEK_PACKAGE_TARGET AND NOT PSEMEK_PACKAGE_AS_LIBRARY)
	set(Boost_USE_STATIC_LIBS ON)
endif()

add_subdirectory(tools)
add_subdirectory(libs)

set(PSEMEK_SOURCES)
if(NOT PSEMEK_PARENT_DIRECTORY)
	list(APPEND PSEMEK_SOURCES todo.md)
endif()

psemek_add_library(psemek EXCLUDE_FROM_ALL ${PSEMEK_SOURCES})
target_link_libraries(psemek INTERFACE ${PSEMEK_LIBRARIES})
set_target_properties(psemek PROPERTIES LINKER_LANGUAGE CXX)

option(PSEMEK_EXAMPLES "Build example apps" ON)

if(PSEMEK_EXAMPLES)
	add_subdirectory(examples)
endif()
