# SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
# SPDX-License-Identifier: GPL-3.0-only

SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)

# D-Bus (single-instance / remote control) is Linux-only: Qt6::DBus does not
# exist on Windows or macOS. Default ON on Linux, OFF elsewhere.
IF(UNIX AND NOT APPLE)
    OPTION(JFJOCH_VIEWER_DBUS "Build viewer with D-Bus support (Linux only)" ON)
ELSE()
    OPTION(JFJOCH_VIEWER_DBUS "Build viewer with D-Bus support (Linux only)" OFF)
ENDIF()

SET(JFJOCH_VIEWER_QT_COMPONENTS Core Gui Widgets Charts Concurrent OpenGL OpenGLWidgets)
IF(JFJOCH_VIEWER_DBUS)
    LIST(APPEND JFJOCH_VIEWER_QT_COMPONENTS DBus)
ENDIF()
FIND_PACKAGE(Qt6 COMPONENTS ${JFJOCH_VIEWER_QT_COMPONENTS} REQUIRED)

QT_ADD_RESOURCES(APP_RESOURCES resources/resources.qrc)

ADD_EXECUTABLE(jfjoch_viewer jfjoch_viewer.cpp JFJochViewerWindow.cpp JFJochViewerWindow.h
        JFJochViewerMenu.cpp
        JFJochViewerMenu.h
        image_viewer/JFJochDiffractionImage.cpp
        image_viewer/JFJochDiffractionImage.h
        image_viewer/JFJochSimpleImage.cpp
        image_viewer/JFJochSimpleImage.h
        JFJochImageReadingWorker.cpp
        JFJochImageReadingWorker.h
        RunData.h
        JFJochProcessController.cpp
        JFJochProcessController.h
        JFJochViewerDatasetInfo.cpp
        JFJochViewerDatasetInfo.h
        JFJochViewerSidePanel.cpp
        JFJochViewerSidePanel.h
        widgets/TitleLabel.cpp
        widgets/TitleLabel.h
        charts/JFJochDatasetInfoChartView.cpp
        charts/JFJochDatasetInfoChartView.h
        widgets/JFJochViewerImageStatistics.cpp
        widgets/JFJochViewerImageStatistics.h
        charts/JFJochSimpleChartView.cpp
        charts/JFJochSimpleChartView.h
        JFJochViewerStatusBar.cpp
        JFJochViewerStatusBar.h
        windows/JFJochViewerImageListWindow.cpp
        windows/JFJochViewerImageListWindow.h
        widgets/NumericComboBox.cpp
        widgets/NumericComboBox.h
        windows/JFJochViewerMetadataWindow.cpp
        windows/JFJochViewerMetadataWindow.h
        windows/JFJochMergeStatsWindow.cpp
        windows/JFJochMergeStatsWindow.h
        widgets/NumberLineEdit.cpp
        widgets/NumberLineEdit.h
        widgets/SliderPlusBox.cpp
        widgets/SliderPlusBox.h
        widgets/JFJochViewerSidePanelChart.cpp
        widgets/JFJochViewerSidePanelChart.h
        widgets/JFJochViewerSettingsDock.cpp
        widgets/JFJochViewerSettingsDock.h
        widgets/CollapsibleSection.cpp
        widgets/CollapsibleSection.h
        widgets/ToolbarIcons.cpp
        widgets/ToolbarIcons.h
        widgets/JFJochViewerImageStrip.cpp
        widgets/JFJochViewerImageStrip.h
        windows/JFJochViewerSpotListWindow.cpp
        windows/JFJochViewerSpotListWindow.h
        image_viewer/JFJochAzIntImage.cpp
        image_viewer/JFJochAzIntImage.h
        windows/JFJochViewerReflectionListWindow.cpp
        windows/JFJochViewerReflectionListWindow.h
        toolbar/JFJochViewerToolbarImage.cpp
        toolbar/JFJochViewerToolbarImage.h
        toolbar/JFJochViewerToolbarDisplay.cpp
        toolbar/JFJochViewerToolbarDisplay.h
        SimpleImage.h
        windows/JFJochCalibrationWindow.cpp
        windows/JFJochCalibrationWindow.h
        windows/JFJochHelperWindow.cpp
        windows/JFJochHelperWindow.h
        windows/JFJochLicenseWindow.cpp
        windows/JFJochLicenseWindow.h
        image_viewer/JFJochImage.cpp
        image_viewer/JFJochImage.h
        windows/JFJoch2DAzintImageWindow.cpp
        windows/JFJoch2DAzintImageWindow.h
        widgets/JFJochViewerROIResult.cpp
        widgets/JFJochViewerROIResult.h
        widgets/JFJochViewerROIList.cpp
        widgets/JFJochViewerROIList.h
        widgets/ResolutionRingWidget.cpp
        widgets/ResolutionRingWidget.h
        image_viewer/JFJochGridScanImage.cpp
        image_viewer/JFJochGridScanImage.h
        widgets/PowderCalibrationWidget.cpp
        widgets/PowderCalibrationWidget.h
        ${APP_RESOURCES}
        windows/JFJochViewerReciprocalSpaceWindow.cpp
        windows/JFJochViewerReciprocalSpaceWindow.h
        windows/JFJochMagnifierWindow.cpp
        windows/JFJochMagnifierWindow.h
        windows/JFJochProcessingJobsWindow.cpp
        windows/JFJochProcessingJobsWindow.h
)

TARGET_LINK_LIBRARIES(jfjoch_viewer Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Charts Qt6::Concurrent
        Qt6::OpenGL Qt6::OpenGLWidgets
        JFJochReader JFJochLogger JFJochCommon JFJochWriter JFJochImageAnalysis JFJochProcess
        fftw3f)

# Native GUI app per platform: a .app bundle on macOS, GUI subsystem (no console window) on
# Windows. Each property is ignored on the platforms it does not apply to, so set both always.
SET_TARGET_PROPERTIES(jfjoch_viewer PROPERTIES
        MACOSX_BUNDLE    ON
        WIN32_EXECUTABLE ON)

# Application icon: embedded into the .exe via a Windows resource script, and copied into
# the macOS .app bundle (referenced from Info.plist through MACOSX_BUNDLE_ICON_FILE).
IF(WIN32)
    TARGET_SOURCES(jfjoch_viewer PRIVATE resources/jfjoch.rc)
ELSEIF(APPLE)
    SET(_viewer_icns ${CMAKE_CURRENT_SOURCE_DIR}/resources/jfjoch.icns)
    TARGET_SOURCES(jfjoch_viewer PRIVATE ${_viewer_icns})
    SET_SOURCE_FILES_PROPERTIES(${_viewer_icns} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
    SET_TARGET_PROPERTIES(jfjoch_viewer PROPERTIES MACOSX_BUNDLE_ICON_FILE jfjoch.icns)
ENDIF()

INSTALL(TARGETS jfjoch_viewer
        BUNDLE  DESTINATION .   COMPONENT viewer   # macOS .app bundle
        RUNTIME DESTINATION bin COMPONENT viewer)  # Windows .exe / Linux binary

IF(JFJOCH_VIEWER_DBUS)
    TARGET_SOURCES(jfjoch_viewer PRIVATE dbus/JFJochViewerAdaptor.cpp dbus/JFJochViewerAdaptor.h)
    TARGET_LINK_LIBRARIES(jfjoch_viewer Qt6::DBus)
    TARGET_COMPILE_DEFINITIONS(jfjoch_viewer PRIVATE JFJOCH_VIEWER_DBUS)
    INSTALL(
            FILES ${CMAKE_CURRENT_SOURCE_DIR}/dbus/ch.psi.jfjoch_viewer.service
            DESTINATION share/dbus-1/services
            COMPONENT viewer
    )
ENDIF()

INSTALL(
        FILES resources/jfjoch.png
        DESTINATION share/pixmaps
        COMPONENT viewer
)

INSTALL(
        FILES jfjoch_viewer.desktop
        DESTINATION share/applications
        COMPONENT viewer
)

# Platform integration plugin: XCB on Linux, native plugin on Windows/macOS.
IF(WIN32)
    qt_import_plugins(jfjoch_viewer INCLUDE Qt::QWindowsIntegrationPlugin)
ELSEIF(APPLE)
    qt_import_plugins(jfjoch_viewer INCLUDE Qt::QCocoaIntegrationPlugin)
ELSE()
    qt_import_plugins(jfjoch_viewer INCLUDE Qt::QXcbIntegrationPlugin)
ENDIF()

# Bundle the Qt runtime into the install tree at install time: this drives windeployqt on Windows
# and macdeployqt on macOS, copying the Qt shared libraries + plugins next to the app. With a
# static Qt (e.g. our Linux build) there is nothing to copy, so it is a no-op. Requires Qt >= 6.5,
# which is when the OUTPUT_SCRIPT signature and the Linux deploy path landed (6.3/6.4 used the older
# FILENAME_VARIABLE and had no Linux support); skipped on older Qt. NO_UNSUPPORTED_PLATFORM_ERROR
# keeps it from hard-failing on configurations it does not handle.
IF(Qt6_VERSION VERSION_GREATER_EQUAL "6.5")
    qt_generate_deploy_app_script(
            TARGET jfjoch_viewer
            OUTPUT_SCRIPT jfjoch_viewer_deploy_script
            NO_UNSUPPORTED_PLATFORM_ERROR)
    INSTALL(SCRIPT ${jfjoch_viewer_deploy_script} COMPONENT viewer)
ENDIF()

# Bundle the cuFFT runtime DLL next to the viewer so the installed app runs on Windows hosts that
# have an NVIDIA driver but no CUDA toolkit. cuFFT is the ONLY CUDA component we link dynamically
# (cudart and the fast-feedback indexer are static), so it is the one runtime file the toolkit would
# otherwise have to provide; the DLL is self-contained (depends only on KERNEL32). CUDA 13 keeps
# redistributable DLLs in bin/x64, earlier toolkits in bin -- glob both. Windows + GPU build only.
IF(WIN32 AND JFJOCH_CUDA_AVAILABLE)
    FILE(GLOB _cufft_dll
            "${CUDAToolkit_BIN_DIR}/x64/cufft64_*.dll"
            "${CUDAToolkit_BIN_DIR}/cufft64_*.dll")
    IF(NOT _cufft_dll)
        MESSAGE(FATAL_ERROR "cuFFT runtime DLL not found under ${CUDAToolkit_BIN_DIR}")
    ENDIF()
    INSTALL(FILES ${_cufft_dll} DESTINATION bin COMPONENT viewer)
ENDIF()
