cmake_minimum_required(VERSION 3.20)
project(UsdLayerManager VERSION 1.0.0 LANGUAGES C CXX)

# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Add cmake modules path
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")

# Find dependencies
find_package(OpenGL REQUIRED)
find_package(OpenUSD REQUIRED)
find_package(Imgui REQUIRED)
find_package(Glad REQUIRED)

# Collect source files
file(GLOB_RECURSE CORE_SOURCES "src/core/*.cpp")
file(GLOB_RECURSE UI_SOURCES "src/ui/*.cpp")
file(GLOB_RECURSE UTILS_SOURCES "src/utils/*.cpp")
set(MAIN_SOURCE "src/main.cpp")

# Create executable
add_executable(UsdLayerManager
    ${MAIN_SOURCE}
    ${CORE_SOURCES}
    ${UI_SOURCES}
    ${UTILS_SOURCES}
)

# Include directories
target_include_directories(UsdLayerManager PRIVATE
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_SOURCE_DIR}/include
    ${CMAKE_SOURCE_DIR}/third_party/fontawesome
    ${CMAKE_SOURCE_DIR}/third_party/nanosvg
)

# Link libraries
target_link_libraries(UsdLayerManager PRIVATE
    OpenUSD::OpenUSD
    Imgui::Imgui
    Glad::Glad
)

# Platform-specific settings
if(WIN32)
    # Windows-specific settings
    target_compile_definitions(UsdLayerManager PRIVATE
        WIN32_LEAN_AND_MEAN
        NOMINMAX
        _CRT_SECURE_NO_WARNINGS
    )
    
    # Copy runtime DLLs to output directory for each configuration
    add_custom_command(TARGET UsdLayerManager POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:UsdLayerManager>"
        # OpenUSD lib/ — usd_*.dll, boost_*.dll, Alembic.dll, etc.
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_BIN_DIR}"
            "$<TARGET_FILE_DIR:UsdLayerManager>"
        # OpenUSD bin/ — tbb.dll, MaterialX, OpenEXR, OpenImageIO, etc.
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/bin"
            "$<TARGET_FILE_DIR:UsdLayerManager>"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/lib/usd"
            "$<TARGET_FILE_DIR:UsdLayerManager>/usd"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/plugin/usd"
            "$<TARGET_FILE_DIR:UsdLayerManager>/usd"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
            "$<TARGET_FILE_DIR:UsdLayerManager>"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
            "$<TARGET_FILE_DIR:UsdLayerManager>"
        COMMENT "Copying runtime DLLs and USD plugins..."
    )
endif()

# Compiler warnings
if(MSVC)
    target_compile_options(UsdLayerManager PRIVATE /W4)
else()
    target_compile_options(UsdLayerManager PRIVATE -Wall -Wextra -Wpedantic)
endif()

# Install rules
install(TARGETS UsdLayerManager
    RUNTIME DESTINATION bin
)

# Install all OpenUSD runtime DLLs (same set that POST_BUILD copies to build/Release).
# Without these the exe cannot start from install/bin.
install(DIRECTORY ${OpenUSD_BIN_DIR}/
    DESTINATION bin
    FILES_MATCHING PATTERN "*.dll"
)

# Install OpenUSD bin/ DLLs — tbb.dll, tbbmalloc.dll, MaterialX, OpenEXR,
# OpenImageIO, zlib, etc.  These are separate from lib/ and also required at runtime.
install(DIRECTORY ${OpenUSD_ROOT_DIR}/bin/
    DESTINATION bin
    FILES_MATCHING PATTERN "*.dll"
)

install(DIRECTORY ${OpenUSD_ROOT_DIR}/lib/usd
    DESTINATION bin
)

install(DIRECTORY ${OpenUSD_ROOT_DIR}/plugin/usd
    DESTINATION bin/usd
)

install(FILES ${OpenUSD_ROOT_DIR}/plugin/usd/hdStorm.dll
    DESTINATION bin
)

# Install Python runtime DLLs required by OpenUSD.
install(FILES
    "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
    "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
    DESTINATION bin
    OPTIONAL   # OPTIONAL so the install doesn't fail on machines with a
               # system-wide Python; in that case the DLL is on PATH already.
)

# Copy resources to build directory
file(COPY ${CMAKE_SOURCE_DIR}/resources
    DESTINATION ${CMAKE_BINARY_DIR}
)

# Copy font and SVG icons to build directory
add_custom_command(TARGET UsdLayerManager POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:UsdLayerManager>/../resources/font"
    COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:UsdLayerManager>/resources/icons"
    COMMAND ${CMAKE_COMMAND} -E copy
        "${CMAKE_SOURCE_DIR}/third_party/Inter/Inter.ttc"
        "$<TARGET_FILE_DIR:UsdLayerManager>/resources/font/Inter.ttc"
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${CMAKE_SOURCE_DIR}/resources/icons"
        "$<TARGET_FILE_DIR:UsdLayerManager>/resources/icons"
    COMMENT "Copying fonts and SVG icons to build output"
)

# Install resources (icons, fonts placeholder) next to the exe so the
# exe-relative path "resources/..." resolves correctly from install/bin/.
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources
    DESTINATION bin
)

# Install Inter font next to the exe under resources/font/
# ImGuiContext tries "resources/font/Inter.ttf" then "resources/font/Inter.ttc".
install(FILES ${CMAKE_SOURCE_DIR}/third_party/Inter/Inter.ttc
    DESTINATION bin/resources/font
)

# Print configuration summary
message(STATUS "")
message(STATUS "=== USD Layer Manager Configuration ===")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "C++ standard: ${CMAKE_CXX_STANDARD}")
message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}")
message(STATUS "OpenUSD found: ${OpenUSD_FOUND}")
message(STATUS "ImGui found: ${Imgui_FOUND}")
message(STATUS "OpenGL found: ${OPENGL_FOUND}")
message(STATUS "Glad found: ${Glad_FOUND}")
message(STATUS "Build tests: ${BUILD_TESTS}")
message(STATUS "=======================================")
message(STATUS "")

# === Test build option ===
option(BUILD_TESTS "Build test executables" OFF)

if(BUILD_TESTS)

# === Viewport Display Test ===
add_executable(ViewportDisplayTest
    tests/viewport_display_test.cpp
    ${CORE_SOURCES}
    ${UTILS_SOURCES}
)

target_include_directories(ViewportDisplayTest PRIVATE
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_SOURCE_DIR}/include
)

target_link_libraries(ViewportDisplayTest PRIVATE
    OpenUSD::OpenUSD
    Glad::Glad
)

if(WIN32)
    target_compile_definitions(ViewportDisplayTest PRIVATE
        WIN32_LEAN_AND_MEAN
        NOMINMAX
        _CRT_SECURE_NO_WARNINGS
    )

    add_custom_command(TARGET ViewportDisplayTest POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_BIN_DIR}"
            "$<TARGET_FILE_DIR:ViewportDisplayTest>"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/lib/usd"
            "$<TARGET_FILE_DIR:ViewportDisplayTest>/usd"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/plugin/usd"
            "$<TARGET_FILE_DIR:ViewportDisplayTest>/usd"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
            "$<TARGET_FILE_DIR:ViewportDisplayTest>"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
            "$<TARGET_FILE_DIR:ViewportDisplayTest>"
        COMMENT "Copying runtime DLLs and USD plugins for test..."
    )
endif()

enable_testing()
add_test(NAME ViewportDisplayTest COMMAND ViewportDisplayTest)

add_executable(RendererDiagnosticTest
    tests/renderer_diagnostic_test.cpp
    ${CORE_SOURCES}
    ${UTILS_SOURCES}
)

target_include_directories(RendererDiagnosticTest PRIVATE
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_SOURCE_DIR}/include
)

target_link_libraries(RendererDiagnosticTest PRIVATE
    OpenUSD::OpenUSD
    Glad::Glad
)

if(WIN32)
    target_compile_definitions(RendererDiagnosticTest PRIVATE
        WIN32_LEAN_AND_MEAN
        NOMINMAX
        _CRT_SECURE_NO_WARNINGS
    )

    add_custom_command(TARGET RendererDiagnosticTest POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_BIN_DIR}"
            "$<TARGET_FILE_DIR:RendererDiagnosticTest>"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/lib/usd"
            "$<TARGET_FILE_DIR:RendererDiagnosticTest>/usd"
        COMMAND ${CMAKE_COMMAND} -E copy_directory
            "${OpenUSD_ROOT_DIR}/plugin/usd"
            "$<TARGET_FILE_DIR:RendererDiagnosticTest>/usd"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python312.dll"
            "$<TARGET_FILE_DIR:RendererDiagnosticTest>"
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "$ENV{LOCALAPPDATA}/Programs/Python/Python312/python3.dll"
            "$<TARGET_FILE_DIR:RendererDiagnosticTest>"
        COMMENT "Copying runtime DLLs and USD plugins for diagnostic test..."
    )
endif()

endif() # BUILD_TESTS
