cmake_minimum_required(VERSION 3.16)
project(Zentris C CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

# GLFW: the system one by default; ZENTRIS_BUNDLE_GLFW=ON (used for Python wheels) builds it from
# source and links it statically, so the binaries only need the system's OpenGL/X11 at runtime.
option(ZENTRIS_BUNDLE_GLFW "Build GLFW from source and link it statically" OFF)
if(NOT ZENTRIS_BUNDLE_GLFW)
  find_package(glfw3 QUIET)
endif()
if(ZENTRIS_BUNDLE_GLFW OR NOT glfw3_FOUND)
  include(FetchContent)
  set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
  set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
  set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
  set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
  set(GLFW_BUILD_WAYLAND OFF CACHE BOOL "" FORCE) # X11 (also runs under XWayland)
  set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
  FetchContent_Declare(glfw GIT_REPOSITORY https://github.com/glfw/glfw.git GIT_TAG 3.4 GIT_SHALLOW TRUE)
  FetchContent_MakeAvailable(glfw)
endif()
find_package(Threads REQUIRED)

# OpenGL 3.3 core function loader (generated by glad, loaded at runtime through GLFW).
add_library(glad STATIC third_party/glad/src/gl.c)
target_include_directories(glad PUBLIC third_party/glad/include)
set_target_properties(glad PROPERTIES POSITION_INDEPENDENT_CODE ON)

# Audio decoding, analysis and song planning, shared by the game and the analysis viewer.
add_library(zencore STATIC
  src/analysis.cpp
  src/audio.cpp
  src/library.cpp
  src/songplan.cpp
  src/youtube.cpp
  src/platform.cpp
  src/third_party_impl.cpp
)
target_include_directories(zencore PUBLIC src third_party)
target_link_libraries(zencore PUBLIC Threads::Threads ${CMAKE_DL_LIBS})
if(UNIX)
  target_link_libraries(zencore PUBLIC m)
endif()
if(MSVC)
  target_compile_options(zencore PUBLIC /utf-8 /bigobj)
  target_compile_definitions(zencore PUBLIC _CRT_SECURE_NO_WARNINGS NOMINMAX _USE_MATH_DEFINES)
endif()

# The game.
add_executable(zentris
  src/main.cpp
  src/game.cpp
  src/input.cpp
  src/theme.cpp
  src/renderer.cpp
)
target_link_libraries(zentris PRIVATE zencore glfw glad)
# Gamepad mappings (SDL_GameControllerDB): looked up next to the executable, then in the sources.
target_compile_definitions(zentris PRIVATE ZEN_SOURCE_DIR="${CMAKE_SOURCE_DIR}")
add_custom_command(TARGET zentris POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different
                   ${CMAKE_SOURCE_DIR}/third_party/gamecontrollerdb.txt $<TARGET_FILE_DIR:zentris>/gamecontrollerdb.txt)

# zenscope: shows what the analysis hears in a song (structure, scene levels, pulses, spectrum, beats).
add_executable(zenscope src/zenscope.cpp)
target_link_libraries(zenscope PRIVATE zencore glfw glad)

foreach(t zencore zentris zenscope)
  target_compile_definitions(${t} PRIVATE GLFW_INCLUDE_NONE)
  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    target_compile_options(${t} PRIVATE -Wall -Wno-unused-function -Wno-missing-field-initializers)
  endif()
endforeach()

# Python wheel (scikit-build-core): the binaries and data go inside the zentris package.
if(SKBUILD)
  install(TARGETS zentris zenscope RUNTIME DESTINATION zentris/bin)
  install(FILES third_party/gamecontrollerdb.txt DESTINATION zentris/bin)
endif()
