cmake_minimum_required(VERSION 3.31)
# Older Ninja generators can quote DEP_FILE as a literal filename for external
# sources under paths containing parentheses/spaces, silently losing header
# dependencies (Kitware/CMake #26287). That can link mixed Settings ABIs.
project(BuzzLauncher VERSION 0.1.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
include(FetchContent)
include(CTest)
# Standalone from the game/SDK: no Python, generated game files or PS3Recomp
# upgrade is required to build the launcher. Dependencies are source/hash pinned.
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
set(SDL_STATIC ON CACHE BOOL "" FORCE)
set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE)
set(SDL_TESTS OFF CACHE BOOL "" FORCE)
set(SDL_EXAMPLES OFF CACHE BOOL "" FORCE)
set(SDL_AUDIO OFF CACHE BOOL "" FORCE)
set(SDL_GPU OFF CACHE BOOL "" FORCE)
set(SDL_VULKAN OFF CACHE BOOL "" FORCE)
# The launcher does not inject desktop input; XTEST is not needed.
set(SDL_X11_XTEST OFF CACHE BOOL "" FORCE)
set(JSON_BuildTests OFF CACHE BOOL "" FORCE)
set(JSON_Install OFF CACHE BOOL "" FORCE)
FetchContent_Declare(SDL3
    URL https://codeload.github.com/libsdl-org/SDL/tar.gz/829a65d769d935c4852f8159e964312c0957260a
    URL_HASH SHA256=48e15cf1a6928453d77afa955d1fdfbbca9169e2bc3d76d111acb9b8bb076d66)
FetchContent_Declare(imgui
    URL https://codeload.github.com/ocornut/imgui/tar.gz/6d910d5487d11ca567b61c7824b0c78c569d62f0
    URL_HASH SHA256=b715a3226320aaebaea79dc6af6405ae37cdcb479817fddaef12a17d8bd15a3a)
FetchContent_Declare(nlohmann_json
    URL https://codeload.github.com/nlohmann/json/tar.gz/65ee68451d8eb2b5f3a30b410476ab83deb3289b
    URL_HASH SHA256=13ef31d691947940a08909f8e0772f1d7d68e5da1678ee812a49c4bb0c996b2f)
FetchContent_Declare(picosha2
    URL https://codeload.github.com/okdshin/PicoSHA2/tar.gz/161cb3fc4170fa7a3eca9e582cebd27cc4d1fe29
    URL_HASH SHA256=6cf473a00c98298d3ddee0aed853e3c799791f49dbc01c996ea46cb248e85802
    SOURCE_SUBDIR header-only)
# PicoSHA2's upstream CMake builds examples/tests; use its header only.
FetchContent_MakeAvailable(SDL3 imgui nlohmann_json picosha2)
add_library(buzz_launcher_core STATIC core.cpp shared_settings.cpp process.cpp ../../port/buzzer_input_config.cpp ../../port/pc_settings.cpp ../../port/pc_settings_file.cpp)
target_include_directories(buzz_launcher_core PUBLIC . ../../port PRIVATE ${picosha2_SOURCE_DIR})
target_link_libraries(buzz_launcher_core PUBLIC nlohmann_json::nlohmann_json SDL3::SDL3-static)
add_library(buzz_launcher_ui STATIC
    ${imgui_SOURCE_DIR}/imgui.cpp ${imgui_SOURCE_DIR}/imgui_draw.cpp
    ${imgui_SOURCE_DIR}/imgui_tables.cpp ${imgui_SOURCE_DIR}/imgui_widgets.cpp
    ${imgui_SOURCE_DIR}/backends/imgui_impl_sdl3.cpp
    ${imgui_SOURCE_DIR}/backends/imgui_impl_sdlrenderer3.cpp
    ${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp)
target_include_directories(buzz_launcher_ui PUBLIC ${imgui_SOURCE_DIR} ${imgui_SOURCE_DIR}/backends ${imgui_SOURCE_DIR}/misc/cpp)
target_link_libraries(buzz_launcher_ui PUBLIC SDL3::SDL3-static)
add_executable(BuzzLauncher WIN32 main.cpp ui.cpp)
target_link_libraries(BuzzLauncher PRIVATE buzz_launcher_core buzz_launcher_ui)
if(MSVC)
    target_compile_options(buzz_launcher_core PRIVATE /W4 /utf-8)
    target_compile_options(BuzzLauncher PRIVATE /W4 /utf-8)
else()
    target_compile_options(buzz_launcher_core PRIVATE -Wall -Wextra -Wpedantic)
    target_compile_options(BuzzLauncher PRIVATE -Wall -Wextra -Wpedantic)
endif()
if(BUILD_TESTING)
    include("${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/BuzzPhone.cmake")
    add_executable(phone_sessions_test ../../tests/phone-sessions-test.cpp ../../port/phone_sessions.cpp)
    add_test(NAME phone-sessions COMMAND phone_sessions_test)
    add_executable(phone_server_test ../../tests/phone-server-test.cpp)
    target_link_libraries(phone_server_test PRIVATE buzz_phone)
    add_test(NAME phone-server COMMAND phone_server_test)
    set_tests_properties(phone-server PROPERTIES TIMEOUT 30)
    add_executable(launcher_native_test ../../tests/launcher-native-test.cpp)
    target_link_libraries(launcher_native_test PRIVATE buzz_launcher_core)
    if(MSVC)
        target_compile_options(launcher_native_test PRIVATE /utf-8)
    endif()
    add_test(NAME launcher-native COMMAND launcher_native_test)
    add_executable(shared_settings_test ../../tests/shared-settings-test.cpp)
    target_link_libraries(shared_settings_test PRIVATE buzz_launcher_core)
    if(MSVC)
        target_compile_options(shared_settings_test PRIVATE /utf-8)
    endif()
    add_test(NAME shared-settings COMMAND shared_settings_test)
    add_executable(buzzer_hid_test ../../tests/buzzer-hid-test.cpp)
    add_test(NAME buzzer-hid COMMAND buzzer_hid_test)
    if(WIN32)
        add_executable(buzzer_hid_win32_test ../../tests/buzzer-hid-win32-test.cpp)
        add_test(NAME buzzer-hid-win32 COMMAND buzzer_hid_win32_test)
        add_executable(buzzer_host_menu_test ../../tests/buzzer-host-menu-test.cpp)
        target_link_libraries(buzzer_host_menu_test PRIVATE buzz_launcher_core)
        add_test(NAME buzzer-host-menu COMMAND buzzer_host_menu_test)
    endif()
    add_executable(pc_settings_test ../../tests/pc-settings-test.cpp)
    target_link_libraries(pc_settings_test PRIVATE buzz_launcher_core)
    add_test(NAME pc-settings COMMAND pc_settings_test)
    # Optional SDK test: a standalone launcher can build without submodules.
    if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../ps3recomp/libs/system/host_controls.c")
        add_executable(game_host_paths_test ../../tests/game-host-paths-test.cpp ../../ps3recomp/libs/system/cellGame.c)
        target_include_directories(game_host_paths_test PRIVATE ../../ps3recomp/include ../../ps3recomp/libs/system)
        add_test(NAME game-host-paths COMMAND game_host_paths_test)
        add_library(buzz_host_controls STATIC ../../ps3recomp/libs/system/host_controls.c)
        target_include_directories(buzz_host_controls PUBLIC ../../ps3recomp/include)
        add_executable(host_controls_test ../../tests/host-controls-test.cpp)
        target_link_libraries(host_controls_test PRIVATE buzz_host_controls SDL3::SDL3-static)
        add_test(NAME host-controls COMMAND host_controls_test)
        add_executable(host_overlay_test ../../tests/host-overlay-test.cpp ../../ps3recomp/libs/system/host_overlay.c)
        target_include_directories(host_overlay_test PRIVATE ../../ps3recomp/include)
        add_test(NAME host-overlay COMMAND host_overlay_test)
        add_library(buzz_pc_runtime STATIC ../../port/pc_runtime.cpp ../../port/pc_texture_upscaler.cpp)
        target_link_libraries(buzz_pc_runtime PUBLIC buzz_launcher_core buzz_host_controls buzz_phone)
        add_executable(pc_runtime_test ../../tests/pc-runtime-test.cpp)
        target_link_libraries(pc_runtime_test PRIVATE buzz_pc_runtime)
        if(MSVC)
            target_compile_options(pc_runtime_test PRIVATE /utf-8)
        endif()
        add_test(NAME pc-runtime COMMAND pc_runtime_test)
    endif()
    add_test(NAME launcher-ui-hidden COMMAND BuzzLauncher --smoke)
    set_tests_properties(launcher-ui-hidden PROPERTIES ENVIRONMENT "SDL_VIDEO_DRIVER=dummy;SDL_RENDER_DRIVER=software" TIMEOUT 30)
    add_test(NAME launcher-reject-unbounded-intro-skip COMMAND BuzzLauncher --launch --test-skip-intro)
    add_test(NAME launcher-reject-nonlaunch-intro-skip COMMAND BuzzLauncher --dry-run --test-seconds 1 --test-skip-intro)
    set_tests_properties(launcher-reject-unbounded-intro-skip launcher-reject-nonlaunch-intro-skip PROPERTIES WILL_FAIL TRUE TIMEOUT 5)
endif()
install(TARGETS BuzzLauncher RUNTIME DESTINATION .)
install(FILES ${SDL3_SOURCE_DIR}/LICENSE.txt DESTINATION licenses RENAME SDL3.txt)
install(FILES ${imgui_SOURCE_DIR}/LICENSE.txt DESTINATION licenses RENAME ImGui.txt)
install(FILES ${nlohmann_json_SOURCE_DIR}/LICENSE.MIT DESTINATION licenses RENAME nlohmann-json.txt)
install(FILES ${picosha2_SOURCE_DIR}/LICENSE DESTINATION licenses RENAME PicoSHA2.txt)
install(FILES ../../LICENSE DESTINATION licenses RENAME Buzz-port.txt)
set(CPACK_PACKAGE_NAME BuzzLauncher)
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_GENERATOR "ZIP;TGZ")
include(CPack)
