cmake_minimum_required(VERSION 3.20)

# Integrate vcpkg toolchain if available
if(DEFINED ENV{VCPKG_ROOT})
    set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
elseif(EXISTS "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake")
    set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
elseif(EXISTS "C:/Users/Gregor Klevže/vcpkg/scripts/buildsystems/vcpkg.cmake")
    set(CMAKE_TOOLCHAIN_FILE "C:/Users/Gregor Klevže/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
endif()

# The toolchain file must be set before calling project()
if(DEFINED CMAKE_TOOLCHAIN_FILE)
    message(STATUS "Using vcpkg toolchain: ${CMAKE_TOOLCHAIN_FILE}")
    set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" CACHE STRING "" FORCE)
endif()

project(spacetris_sdl3 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find SDL3 (via package manager or a local build)
# vcpkg example: vcpkg install sdl3
# Homebrew: brew install sdl3
find_package(SDL3 CONFIG REQUIRED)
find_package(SDL3_ttf CONFIG REQUIRED)
find_package(SDL3_image CONFIG REQUIRED)
find_package(cpr CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)

set(TETRIS_SOURCES
    src/main.cpp
    src/app/TetrisApp.cpp
    src/gameplay/core/Game.cpp
    src/gameplay/coop/CoopGame.cpp
    src/core/GravityManager.cpp
    src/core/state/StateManager.cpp
    # New core architecture classes
    src/core/application/ApplicationManager.cpp
    src/core/input/InputManager.cpp
    src/core/assets/AssetManager.cpp
    src/core/GlobalState.cpp
    src/core/Settings.cpp
    src/graphics/renderers/RenderManager.cpp
    src/persistence/Scores.cpp
    src/graphics/effects/Starfield.cpp
    src/graphics/effects/Starfield3D.cpp
    src/graphics/effects/SpaceWarp.cpp
    src/graphics/ui/Font.cpp
    src/graphics/ui/HelpOverlay.cpp
    src/graphics/renderers/GameRenderer.cpp
    src/graphics/renderers/UIRenderer.cpp
    src/audio/Audio.cpp
    src/gameplay/effects/LineEffect.cpp
    src/audio/SoundEffect.cpp
    src/ui/MenuLayout.cpp
    src/ui/BottomMenu.cpp
    src/app/BackgroundManager.cpp
    src/app/Fireworks.cpp
    src/app/AssetLoader.cpp
    src/app/TextureLoader.cpp
    src/states/LoadingManager.cpp
    # State implementations (new)
    src/states/LoadingState.cpp
    src/states/MenuState.cpp
    src/states/OptionsState.cpp
    src/states/LevelSelectorState.cpp
    src/states/PlayingState.cpp
)


if(APPLE)
    set(APP_ICON "${CMAKE_SOURCE_DIR}/assets/favicon/AppIcon.icns")
    if(EXISTS "${APP_ICON}")
        add_executable(spacetris MACOSX_BUNDLE ${TETRIS_SOURCES} "${APP_ICON}")
        set_source_files_properties("${APP_ICON}" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
        set_target_properties(spacetris PROPERTIES 
            MACOSX_BUNDLE_ICON_FILE "AppIcon"
            MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/cmake/MacBundleInfo.plist.in"
        )
    else()
        message(WARNING "App icon not found at ${APP_ICON}; bundle will use default icon")
        add_executable(spacetris MACOSX_BUNDLE ${TETRIS_SOURCES})
        set_target_properties(spacetris PROPERTIES
            MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/cmake/MacBundleInfo.plist.in"
        )
    endif()
else()
    add_executable(spacetris ${TETRIS_SOURCES})
endif()

# Ensure the built executable is named `spacetris`.
set_target_properties(spacetris PROPERTIES OUTPUT_NAME "spacetris")

if (WIN32)
    # No compatibility copy; built executable is `spacetris`.
endif()

if (WIN32)
    # Embed the application icon into the executable
    set_source_files_properties(src/app_icon.rc PROPERTIES LANGUAGE RC)
    target_sources(spacetris PRIVATE src/app_icon.rc)
endif()

if(MSVC)
    # Prevent PDB write contention on MSVC by enabling /FS for this target
    target_compile_options(spacetris PRIVATE /FS)
endif()

if (WIN32)
    # Ensure favicon.ico is available in the build directory for the resource compiler
    set(FAVICON_SRC "${CMAKE_SOURCE_DIR}/assets/favicon/favicon.ico")
    set(FAVICON_DEST "${CMAKE_BINARY_DIR}/favicon.ico")
    if(EXISTS ${FAVICON_SRC})
        add_custom_command(
            OUTPUT ${FAVICON_DEST}
            COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FAVICON_SRC} ${FAVICON_DEST}
            DEPENDS ${FAVICON_SRC}
            COMMENT "Copy favicon.ico to build dir for resource compilation"
        )
        add_custom_target(copy_favicon ALL DEPENDS ${FAVICON_DEST})
        add_dependencies(spacetris copy_favicon)
    else()
        message(WARNING "Favicon not found at ${FAVICON_SRC}; app icon may not compile")
    endif()

    # Also copy favicon into the runtime output folder (same dir as exe)
    add_custom_command(TARGET spacetris POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FAVICON_SRC} $<TARGET_FILE_DIR:spacetris>/favicon.ico
        COMMENT "Copy favicon.ico next to executable"
    )
endif()

if(APPLE)
    set(_mac_copy_commands)
    if(EXISTS "${CMAKE_SOURCE_DIR}/assets")
        list(APPEND _mac_copy_commands
            COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/assets" "$<TARGET_FILE_DIR:spacetris>/assets"
        )
    endif()
    if(EXISTS "${CMAKE_SOURCE_DIR}/fonts")
        list(APPEND _mac_copy_commands
            COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/fonts" "$<TARGET_FILE_DIR:spacetris>/fonts"
        )
    endif()
    if(EXISTS "${CMAKE_SOURCE_DIR}/FreeSans.ttf")
        list(APPEND _mac_copy_commands
            COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/FreeSans.ttf" "$<TARGET_FILE_DIR:spacetris>/FreeSans.ttf"
        )
    endif()
    if(_mac_copy_commands)
        add_custom_command(TARGET spacetris POST_BUILD
            ${_mac_copy_commands}
            COMMENT "Copying game assets into macOS bundle"
        )
    endif()
endif()

target_link_libraries(spacetris PRIVATE SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image cpr::cpr nlohmann_json::nlohmann_json)

if (WIN32)
    target_link_libraries(spacetris PRIVATE mfplat mfreadwrite mfuuid)
endif()
if(APPLE)
    # Needed for MP3 decoding via AudioToolbox on macOS
    target_link_libraries(spacetris PRIVATE "-framework AudioToolbox" "-framework CoreFoundation")
endif()

# Include production build configuration
include(cmake/ProductionBuild.cmake)

# Enable CTest so `add_test` registers tests for `ctest`
enable_testing()

# Unit tests (simple runner)
find_package(Catch2 CONFIG REQUIRED)
add_executable(spacetris_tests
    tests/GravityTests.cpp
    src/core/GravityManager.cpp
)
target_include_directories(spacetris_tests PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(spacetris_tests PRIVATE Catch2::Catch2WithMain)
add_test(NAME GravityTests COMMAND spacetris_tests)

if(EXISTS "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/include")
    target_include_directories(spacetris_tests PRIVATE "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/include")
endif()

# Add new src subfolders to include path so old #includes continue to work
target_include_directories(spacetris PRIVATE
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_SOURCE_DIR}/src/audio
    ${CMAKE_SOURCE_DIR}/src/gameplay
    ${CMAKE_SOURCE_DIR}/src/graphics
    ${CMAKE_SOURCE_DIR}/src/persistence
    ${CMAKE_SOURCE_DIR}/src/core
    ${CMAKE_SOURCE_DIR}/src/states
)