cmake_minimum_required(VERSION 3.24)
project(miskeyed-xr-agent VERSION 0.1.0 LANGUAGES CXX)

include(CTest)
include(GNUInstallDirs)
option(MISKEYED_XR_BUILD_OPENXR "Build the OpenXR probe/backend" ON)
option(MISKEYED_XR_FETCH_OPENXR "Fetch Khronos OpenXR SDK when it is not installed" ON)
option(MISKEYED_XR_BUILD_EXAMPLES "Build hardware-free host integration examples" ON)
option(MISKEYED_XR_BUILD_PYTHON "Build the pybind11 Python module" OFF)
option(MISKEYED_XR_INSTALL_NATIVE_SDK "Install C++ headers, library, and CMake targets" ON)

add_library(miskeyed-spatial
  src/spatial/spatial_intent.cpp
  src/spatial/intent_timeline.cpp
  src/spatial/jsonl.cpp)
add_library(miskeyed::spatial ALIAS miskeyed-spatial)
set_target_properties(miskeyed-spatial PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(miskeyed-spatial PROPERTIES EXPORT_NAME spatial)
target_compile_features(miskeyed-spatial PUBLIC cxx_std_20)
target_include_directories(miskeyed-spatial PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_options(miskeyed-spatial PRIVATE $<$<CXX_COMPILER_ID:GNU,Clang>:-Wall;-Wextra;-Wpedantic;-Werror>)

if(MISKEYED_XR_BUILD_OPENXR)
  find_package(OpenXR CONFIG QUIET)
  if(NOT OpenXR_FOUND AND MISKEYED_XR_FETCH_OPENXR)
    include(FetchContent)
    set(BUILD_API_LAYERS OFF CACHE BOOL "" FORCE)
    set(BUILD_TESTS OFF CACHE BOOL "" FORCE)
    set(BUILD_CONFORMANCE_TESTS OFF CACHE BOOL "" FORCE)
    set(DYNAMIC_LOADER OFF CACHE BOOL "" FORCE)
    FetchContent_Declare(openxr_sdk
      URL https://github.com/KhronosGroup/OpenXR-SDK-Source/archive/refs/tags/release-1.1.49.tar.gz
      URL_HASH SHA256=207452a51ec9d730742c385adb5af21fb266fa7be8090b251f76c0bd2b433c61
      DOWNLOAD_EXTRACT_TIMESTAMP FALSE)
    FetchContent_MakeAvailable(openxr_sdk)
  endif()
  if(TARGET OpenXR::openxr_loader)
    add_library(miskeyed-openxr src/openxr/probe.cpp src/openxr/session_input.cpp)
    add_library(miskeyed::openxr ALIAS miskeyed-openxr)
    target_compile_features(miskeyed-openxr PUBLIC cxx_std_20)
    target_include_directories(miskeyed-openxr PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
    # OpenXR types are part of SessionInput's public native header.
    target_link_libraries(miskeyed-openxr PUBLIC miskeyed-spatial OpenXR::openxr_loader)
    target_compile_options(miskeyed-openxr PRIVATE $<$<CXX_COMPILER_ID:GNU,Clang>:-Wall;-Wextra;-Wpedantic;-Werror>)
    add_executable(xr-agent-probe apps/xr-agent-probe/main.cpp)
    target_link_libraries(xr-agent-probe PRIVATE miskeyed-openxr)
  else()
    message(FATAL_ERROR "OpenXR requested, but official loader target OpenXR::openxr_loader is unavailable")
  endif()
endif()

if(MISKEYED_XR_BUILD_EXAMPLES)
  add_executable(spatial-host-example examples/host-integration/main.cpp)
  target_link_libraries(spatial-host-example PRIVATE miskeyed-spatial)
endif()

if(MISKEYED_XR_BUILD_PYTHON)
  find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
  find_package(pybind11 CONFIG REQUIRED)
  pybind11_add_module(_spatial MODULE python/bindings.cpp)
  target_link_libraries(_spatial PRIVATE miskeyed-spatial)
  install(TARGETS _spatial DESTINATION miskeyed/xr/agent)
endif()

if(MISKEYED_XR_INSTALL_NATIVE_SDK)
  install(TARGETS miskeyed-spatial EXPORT miskeyed-xr-agent-targets
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
  install(DIRECTORY include/miskeyed/spatial DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/miskeyed)
  install(EXPORT miskeyed-xr-agent-targets
    FILE miskeyed-xr-agent-targets.cmake
    NAMESPACE miskeyed::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/miskeyed-xr-agent)
  install(FILES cmake/miskeyed-xr-agent-config.cmake
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/miskeyed-xr-agent)
endif()

if(BUILD_TESTING)
  add_executable(spatial-tests tests/spatial_tests.cpp)
  target_link_libraries(spatial-tests PRIVATE miskeyed-spatial)
  add_test(NAME spatial-tests COMMAND spatial-tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/frames.jsonl)
endif()
