cmake_minimum_required(VERSION 3.29)

project(PanoPainter
    VERSION 0.0.0
    DESCRIPTION "Panoramic painting and animation application"
    LANGUAGES C CXX)

if(POLICY CMP0091)
    cmake_policy(SET CMP0091 NEW)
endif()

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(PanoPainterOptions)
if(PP_ENABLE_ASAN AND MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
else()
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
endif()
include(PanoPainterWarnings)
include(PanoPainterSources)
include(PanoPainterVersion)
include(PanoPainterRuntime)

if(PP_ENABLE_CLANG_TIDY)
    find_program(PP_CLANG_TIDY_EXE NAMES clang-tidy)
    if(PP_CLANG_TIDY_EXE)
        set(CMAKE_CXX_CLANG_TIDY "${PP_CLANG_TIDY_EXE}")
    else()
        message(WARNING "PP_ENABLE_CLANG_TIDY is ON but clang-tidy was not found.")
    endif()
endif()

if(PP_ENABLE_CPPCHECK)
    find_program(PP_CPPCHECK_EXE NAMES cppcheck)
    if(PP_CPPCHECK_EXE)
        set(CMAKE_CXX_CPPCHECK
            "${PP_CPPCHECK_EXE}"
            "--enable=warning,style,performance,portability"
            "--inline-suppr"
            "--suppress=missingIncludeSystem")
    else()
        message(WARNING "PP_ENABLE_CPPCHECK is ON but cppcheck was not found.")
    endif()
endif()

add_library(pp_project_options INTERFACE)
target_compile_features(pp_project_options INTERFACE cxx_std_23)

add_library(pp_project_warnings INTERFACE)
pp_configure_project_warnings(pp_project_warnings)

if(PP_USE_VCPKG_TINYXML2)
    find_package(tinyxml2 CONFIG REQUIRED)
    add_library(pp_xml_tinyxml2 INTERFACE)
    target_link_libraries(pp_xml_tinyxml2
        INTERFACE
            tinyxml2::tinyxml2)
else()
    add_library(pp_vendor_tinyxml2 STATIC
        libs/tinyxml2/tinyxml2.cpp)
    target_include_directories(pp_vendor_tinyxml2
        SYSTEM PUBLIC
            "${CMAKE_CURRENT_SOURCE_DIR}/libs/tinyxml2")
    target_link_libraries(pp_vendor_tinyxml2
        PUBLIC
            pp_project_options)
    add_library(pp_xml_tinyxml2 ALIAS pp_vendor_tinyxml2)
endif()

add_custom_target(panopainter_modernization_status
    COMMAND "${CMAKE_COMMAND}" -E echo "PanoPainter modernization scaffold configured."
    COMMAND "${CMAKE_COMMAND}" -E echo "Roadmap: docs/modernization/roadmap.md"
    COMMAND "${CMAKE_COMMAND}" -E echo "Debt log: docs/modernization/debt.md"
    VERBATIM)

add_custom_target(panopainter_validate_shaders
    COMMAND "${CMAKE_COMMAND}"
        "-DPP_SHADER_DIR=${CMAKE_CURRENT_SOURCE_DIR}/data/shaders"
        -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ValidatePanoPainterShaders.cmake"
    VERBATIM)

add_library(pp_foundation STATIC
    src/foundation/binary_stream.cpp
    src/foundation/event.cpp
    src/foundation/log.cpp
    src/foundation/parse.cpp
    src/foundation/task_queue.cpp
    src/foundation/trace.cpp)
target_include_directories(pp_foundation
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_foundation
    PUBLIC
        pp_project_options
    PRIVATE
        pp_project_warnings)

add_library(pp_assets STATIC
    src/assets/brush_package.cpp
    src/assets/image_format.cpp
    src/assets/image_metadata.cpp
    src/assets/image_pixels.cpp
    src/assets/ppi_header.cpp
    src/assets/settings_document.cpp)
target_include_directories(pp_assets
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_include_directories(pp_assets
    SYSTEM PRIVATE
        "${CMAKE_CURRENT_SOURCE_DIR}/libs/stb")
if(MSVC)
    set_source_files_properties(src/assets/image_pixels.cpp
        PROPERTIES
            COMPILE_OPTIONS "/analyze-")
endif()
target_link_libraries(pp_assets
    PUBLIC
        pp_foundation
        pp_project_options
    PRIVATE
        pp_project_warnings)

add_library(pp_paint STATIC
    src/paint/brush.cpp
    src/paint/blend.cpp
    src/paint/stroke.cpp
    src/paint/stroke_script.cpp)
target_include_directories(pp_paint
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_paint
    PUBLIC
        pp_foundation
        pp_project_options
    PRIVATE
        pp_project_warnings)

add_library(pp_document STATIC
    src/document/document.cpp
    src/document/ppi_export.cpp
    src/document/ppi_import.cpp)
target_include_directories(pp_document
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_document
    PUBLIC
        pp_foundation
        pp_assets
        pp_paint
        pp_project_options
    PRIVATE
        pp_project_warnings)

add_library(pp_renderer_api STATIC
    src/renderer_api/recording_renderer.cpp
    src/renderer_api/renderer_api.cpp
    src/renderer_api/shader_catalog.cpp)
target_include_directories(pp_renderer_api
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_renderer_api
    PUBLIC
        pp_foundation
        pp_project_options
    PRIVATE
        pp_project_warnings)

if(PP_ENABLE_OPENGL)
    add_library(pp_renderer_gl STATIC
        src/renderer_gl/command_plan.cpp
        src/renderer_gl/opengl_capabilities.cpp
        src/renderer_gl/shader_bindings.cpp)
    target_include_directories(pp_renderer_gl
        PUBLIC
            "${CMAKE_CURRENT_SOURCE_DIR}/src")
    target_link_libraries(pp_renderer_gl
        PUBLIC
            pp_renderer_api
            pp_project_options
        PRIVATE
            pp_project_warnings)
    if(EMSCRIPTEN)
        target_compile_definitions(pp_renderer_gl PRIVATE
            PP_RENDERER_GL_RUNTIME_GLES=1
            PP_RENDERER_GL_RUNTIME_WEB=1)
    elseif(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
        target_compile_definitions(pp_renderer_gl PRIVATE
            PP_RENDERER_GL_RUNTIME_GLES=1)
    else()
        target_compile_definitions(pp_renderer_gl PRIVATE
            PP_RENDERER_GL_RUNTIME_DESKTOP=1)
    endif()
endif()

add_library(pp_paint_renderer STATIC
    src/paint_renderer/compositor.cpp)
target_include_directories(pp_paint_renderer
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_paint_renderer
    PUBLIC
        pp_foundation
        pp_paint
        pp_renderer_api
        pp_project_options
    PRIVATE
        pp_project_warnings)

add_library(pp_ui_core STATIC
    src/ui_core/color.cpp
    src/ui_core/layout_value.cpp
    src/ui_core/layout_xml.cpp)
target_include_directories(pp_ui_core
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_ui_core
    PUBLIC
        pp_foundation
        pp_project_options
    PRIVATE
        pp_xml_tinyxml2
        pp_project_warnings)

add_library(pp_platform_api STATIC
    src/platform_api/asset_file_load_policy.cpp
    src/platform_api/asset_file_load_policy.h
    src/platform_api/network_tls_policy.cpp
    src/platform_api/network_tls_policy.h
    src/platform_api/platform_services.cpp
    src/platform_api/platform_services.h)
target_include_directories(pp_platform_api
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_platform_api
    PUBLIC
        pp_project_options
    PRIVATE
        pp_project_warnings)

add_library(pp_app_core STATIC
    src/app_core/about_menu.h
    src/app_core/app_preferences.h
    src/app_core/app_status.h
    src/app_core/app_startup.h
    src/app_core/brush_package_import.h
    src/app_core/brush_package_export.h
    src/app_core/brush_ui.h
    src/app_core/canvas_hotkey.h
    src/app_core/canvas_tool_ui.h
    src/app_core/document_animation.h
    src/app_core/document_canvas.h
    src/app_core/document_cloud.h
    src/app_core/document_export.cpp
    src/app_core/document_import.h
    src/app_core/document_layer.h
    src/app_core/document_platform_io.h
    src/app_core/document_recording.h
    src/app_core/document_resize.h
    src/app_core/document_route.cpp
    src/app_core/document_sharing.h
    src/app_core/document_session.cpp
    src/app_core/file_menu.h
    src/app_core/grid_ui.h
    src/app_core/history_ui.h
    src/app_core/main_toolbar.h
    src/app_core/quick_ui.h
    src/app_core/tools_menu.h)
target_include_directories(pp_app_core
    PUBLIC
        "${CMAKE_CURRENT_SOURCE_DIR}/src")
target_link_libraries(pp_app_core
    PUBLIC
        pp_foundation
        pp_project_options
    PRIVATE
        pp_project_warnings)

if(PP_BUILD_TOOLS)
    add_subdirectory(tools/pano_cli)
endif()

if(PP_BUILD_TESTS)
    enable_testing()
    add_subdirectory(tests)
endif()

if(PP_BUILD_APP)
    if(WIN32)
        add_library(pp_legacy_vendor OBJECT
            ${PP_VENDOR_SOURCES})
        target_link_libraries(pp_legacy_vendor
            PUBLIC
                pp_project_options
            PRIVATE
                pp_project_warnings)
        target_include_directories(pp_legacy_vendor
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})
        target_compile_definitions(pp_legacy_vendor
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_vendor PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        add_library(pp_legacy_renderer_gl OBJECT
            ${PP_LEGACY_RENDERER_GL_SOURCES})
        target_link_libraries(pp_legacy_renderer_gl
            PUBLIC
                pp_project_options
            PRIVATE
                pp_renderer_api
                pp_project_warnings)
        if(TARGET pp_renderer_gl)
            target_link_libraries(pp_legacy_renderer_gl PRIVATE pp_renderer_gl)
        endif()
        target_include_directories(pp_legacy_renderer_gl
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})
        target_compile_definitions(pp_legacy_renderer_gl
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_renderer_gl PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")
        target_precompile_headers(pp_legacy_renderer_gl PRIVATE src/pch.h)

        add_library(pp_legacy_assets_io OBJECT
            ${PP_LEGACY_ASSETS_IO_SOURCES})
        target_link_libraries(pp_legacy_assets_io
            PUBLIC
                pp_project_options
            PRIVATE
                pp_assets
                pp_platform_api
                pp_project_warnings)
        target_include_directories(pp_legacy_assets_io
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})
        target_compile_definitions(pp_legacy_assets_io
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_assets_io PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")
        target_precompile_headers(pp_legacy_assets_io PRIVATE src/pch.h)

        add_library(pp_legacy_paint_document OBJECT
            ${PP_LEGACY_PAINT_DOCUMENT_SOURCES})
        target_link_libraries(pp_legacy_paint_document
            PUBLIC
                pp_project_options
            PRIVATE
                pp_assets
                pp_document
                pp_paint
                pp_paint_renderer
                pp_platform_api
                pp_renderer_api
                pp_project_warnings)
        if(TARGET pp_renderer_gl)
            target_link_libraries(pp_legacy_paint_document PRIVATE pp_renderer_gl)
        endif()
        target_include_directories(pp_legacy_paint_document
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})
        target_compile_definitions(pp_legacy_paint_document
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_paint_document PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")
        target_precompile_headers(pp_legacy_paint_document PRIVATE src/pch.h)

        add_library(pp_legacy_engine STATIC
            ${PP_LEGACY_ENGINE_SOURCES}
            $<TARGET_OBJECTS:pp_legacy_assets_io>
            $<TARGET_OBJECTS:pp_legacy_paint_document>
            $<TARGET_OBJECTS:pp_legacy_renderer_gl>
            $<TARGET_OBJECTS:pp_legacy_vendor>)

        target_link_libraries(pp_legacy_engine
            PUBLIC
                pp_project_options
            PRIVATE
                pp_assets
                pp_document
                pp_paint
                pp_paint_renderer
                pp_renderer_api
                pp_project_warnings)
        if(TARGET pp_renderer_gl)
            target_link_libraries(pp_legacy_engine PRIVATE pp_renderer_gl)
        endif()

        target_include_directories(pp_legacy_engine
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})

        target_compile_definitions(pp_legacy_engine
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_engine PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        target_precompile_headers(pp_legacy_engine PRIVATE src/pch.h)

        add_library(pp_legacy_ui_core OBJECT
            ${PP_LEGACY_UI_CORE_SOURCES})

        target_link_libraries(pp_legacy_ui_core
            PUBLIC
                pp_app_core
                pp_legacy_engine
                pp_project_options
            PRIVATE
                pp_paint_renderer
                pp_platform_api
                pp_renderer_api
                pp_project_warnings)
        if(TARGET pp_renderer_gl)
            target_link_libraries(pp_legacy_ui_core PRIVATE pp_renderer_gl)
        endif()

        target_include_directories(pp_legacy_ui_core
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})

        target_compile_definitions(pp_legacy_ui_core
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_ui_core PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        target_precompile_headers(pp_legacy_ui_core PRIVATE src/pch.h)

        add_library(pp_legacy_app STATIC
            ${PP_LEGACY_APP_SOURCES}
            $<TARGET_OBJECTS:pp_legacy_ui_core>)

        target_link_libraries(pp_legacy_app
            PUBLIC
                pp_legacy_engine
                pp_legacy_ui_core
                pp_project_options
            PRIVATE
                pp_platform_api
                pp_renderer_api
                pp_project_warnings)
        if(TARGET pp_renderer_gl)
            target_link_libraries(pp_legacy_app PRIVATE pp_renderer_gl)
        endif()

        target_include_directories(pp_legacy_app
            PUBLIC
                ${PP_LEGACY_INCLUDE_DIRS})

        target_compile_definitions(pp_legacy_app
            PUBLIC
                ENUM_BITFIELDS_NOT_SUPPORTED
                UNICODE
                _UNICODE
                _CRT_SECURE_NO_WARNINGS
                _SCL_SECURE_NO_WARNINGS
                _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
                _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
                _CONSOLE
                WITH_CURL=1)
        set_target_properties(pp_legacy_app PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        target_precompile_headers(pp_legacy_app PRIVATE src/pch.h)

        add_library(pp_panopainter_ui STATIC
            ${PP_PANOPAINTER_UI_SOURCES})
        target_link_libraries(pp_panopainter_ui
            PUBLIC
                pp_legacy_app
                pp_project_options
            PRIVATE
                pp_assets
                pp_platform_api
                pp_project_warnings)
        target_precompile_headers(pp_panopainter_ui REUSE_FROM pp_legacy_app)
        set_target_properties(pp_panopainter_ui PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        add_library(panopainter_app STATIC
            ${PP_PANOPAINTER_APP_SOURCES})
        target_include_directories(panopainter_app
            PUBLIC
                "${CMAKE_CURRENT_SOURCE_DIR}/src")
        target_link_libraries(panopainter_app
            PUBLIC
                pp_app_core
                pp_legacy_app
                pp_panopainter_ui
                pp_platform_api
                pp_project_options
            PRIVATE
                pp_project_warnings)
        pp_add_version_generation(panopainter_app "$<IF:$<CONFIG:Debug>,debug,release>")

        add_library(pp_platform_windows OBJECT
            ${PP_WINDOWS_PLATFORM_SOURCES})
        target_link_libraries(pp_platform_windows
            PUBLIC
                panopainter_app
                "${CMAKE_CURRENT_SOURCE_DIR}/libs/bugtrap-client/lib/BugTrapU-x64.lib"
                "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/lib/dll-debug-x64/libcurl_debug.lib>"
                "$<$<NOT:$<CONFIG:Debug>>:${CMAKE_CURRENT_SOURCE_DIR}/libs/curl-win/lib/dll-release-x64/libcurl.lib>"
                "${CMAKE_CURRENT_SOURCE_DIR}/libs/libyuv/lib/win/yuv.lib"
                "${CMAKE_CURRENT_SOURCE_DIR}/libs/mp4v2/lib/win/libmp4v2.lib"
                "${CMAKE_CURRENT_SOURCE_DIR}/libs/openh264/lib/openh264-2.0.0-win64.lib"
                "${CMAKE_CURRENT_SOURCE_DIR}/libs/openvr/lib/win64/openvr_api.lib"
                comdlg32
                gdi32
                opengl32
                ole32
                shell32
                shlwapi
                user32
                wbemuuid
            PRIVATE
                pp_project_options
                pp_project_warnings)
        target_precompile_headers(pp_platform_windows REUSE_FROM pp_legacy_app)
        set_target_properties(pp_platform_windows PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        add_executable(PanoPainter WIN32
            ${PP_WINDOWS_APP_SOURCES}
            $<TARGET_OBJECTS:pp_platform_windows>)

        target_link_libraries(PanoPainter
            PRIVATE
                pp_project_options
                pp_project_warnings
                pp_platform_windows)

        set_target_properties(PanoPainter PROPERTIES
            VS_GLOBAL_CharacterSet "Unicode")

        pp_configure_windows_runtime_payloads(PanoPainter)
    else()
        message(WARNING "PP_BUILD_APP is enabled, but the root CMake app target is currently Windows-only. Platform alignment is tracked in Phase 6.")
    endif()
endif()
