# CMakeLists.txt für Qt6-Migrationstests
# Diese Tests validieren BUILD_RTI Guards, Qt6-Kompatibilität und RTI-Integration

cmake_minimum_required(VERSION 3.16)

# Qt6 finden (wird vom Hauptprojekt gesetzt, aber sicherheitshalber hier auch)
if(QT6_GUI_AVAILABLE)
    # Check if targets already exist from parent CMakeLists.txt
    if(TARGET Qt6::Core AND TARGET Qt6::Gui AND TARGET Qt6::Widgets AND TARGET Qt6::Test)
        # Already found by parent - use existing targets
    elseif(NOT TARGET Qt6::Gui OR NOT TARGET Qt6::Widgets)
        # Manual fallback: create imported targets when standard find fails due to OpenGL
        if(NOT TARGET Qt6::Gui)
            add_library(Qt6::Gui SHARED IMPORTED)
            set_target_properties(Qt6::Gui PROPERTIES
                IMPORTED_LOCATION "/usr/lib/x86_64-linux-gnu/libQt6Gui.so.6"
                INTERFACE_INCLUDE_DIRECTORIES "/usr/include/x86_64-linux-gnu/qt6/QtGui;/usr/include/x86_64-linux-gnu/qt6"
            )
        endif()
        if(NOT TARGET Qt6::Widgets)
            add_library(Qt6::Widgets SHARED IMPORTED)
            set_target_properties(Qt6::Widgets PROPERTIES
                IMPORTED_LOCATION "/usr/lib/x86_64-linux-gnu/libQt6Widgets.so.6"
                INTERFACE_INCLUDE_DIRECTORIES "/usr/include/x86_64-linux-gnu/qt6/QtWidgets;/usr/include/x86_64-linux-gnu/qt6"
                INTERFACE_LINK_LIBRARIES "Qt6::Gui;Qt6::Core"
            )
        endif()
    else()
        # Try standard find_package first, fall back to manual targets if OpenGL missing
        find_package(Qt6 QUIET COMPONENTS Core Gui Widgets Test)
    endif()
    # Ensure Core and Test are found
    if(NOT TARGET Qt6::Core)
        find_package(Qt6 REQUIRED COMPONENTS Core Test)
    endif()
else()
    if(NOT TARGET Qt6::Core OR NOT TARGET Qt6::Test)
        find_package(Qt6 REQUIRED COMPONENTS Core Test)
    endif()
endif()

# Nur bauen wenn BUILD_TESTING aktiviert ist
if(BUILD_TESTING)
    # Try to find system-wide GTest first, fallback to FetchContent
    find_package(GTest QUIET)
    if(NOT TARGET GTest::gtest_main)
        include(FetchContent)
        FetchContent_Declare(
          googletest
          GIT_REPOSITORY https://github.com/google/googletest.git
          GIT_TAG v1.13.0
        )
        # For Windows: Prevent overriding the parent project's compiler/linker settings
        set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
        FetchContent_MakeAvailable(googletest)
    endif()

    # Collect all test source files dynamically
    file(GLOB MIGRATION_TEST_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/test_*.cpp")

    if(MIGRATION_TEST_SOURCES)
        set(EXISTING_SOURCES ${MIGRATION_TEST_SOURCES})
        
        # Exclude tests for non-existent or commented-out components
        list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_lts_app_descriptor_editor\\.cpp")
        # Exclude Qt Test-based tests (conflict with gtest main())
        list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_lts_app_descriptor\\.cpp")
        
        # Exclude Grantlee-related tests when BUILD_GRANTLEE is OFF
        if(NOT BUILD_GRANTLEE)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_.*Grantlee.*\\.cpp")
            message(STATUS "Migration tests: Grantlee support disabled (BUILD_GRANTLEE=OFF), excluded Grantlee tests")
        endif()
        
        # Exclude CodeGen tests when CodeGen targets aren't available (MIGRATE_MODULE restricts scope)
        if(NOT TARGET codegen_base)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_StructBuilder\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_SqlGenerator\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_XmlReader\\.cpp")
            message(STATUS "Migration tests: CodeGen targets not available, excluded CodeGen tests")
        endif()
        
        # Exclude LtsTimelineClassic tests when LtsTimelineClassic target isn't available
        if(NOT TARGET LtsTimelineClassic)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_abstracttimelinemodel\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_event\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_eventdelegate\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_eventgraphic\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_eventlist\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_eventtools\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_item\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_ltsclassicdatamodel\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_ltsclassicfilterproxymodel\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_passiveeventcontainer\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_testtimelinemodel\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_timelineheaderview\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_timelineindicator\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_timelineview\\.cpp")
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_timelinewidget\\.cpp")
            message(STATUS "Migration tests: LtsTimelineClassic target not available, excluded LtsTimelineClassic tests")
        endif()
        
        # Exclude LTS Tools tests when corresponding targets aren't available
        if(NOT TARGET dbAdministration)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DBAdministration\\.cpp")
        endif()
        if(NOT TARGET SettingsRemover)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DBOperatorSettingsRemover\\.cpp")
        endif()
        if(NOT TARGET dbUpdate)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DBUpdate\\.cpp")
        endif()
        if(NOT TARGET tDataSampleGenerator)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DataSampleGenerator\\.cpp")
        endif()
        if(NOT TARGET tDataSampleReceiver)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DataSampleReceiver\\.cpp")
        endif()
        if(NOT TARGET DateTimeSyncer)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DateTimeSyncer\\.cpp")
        endif()
        if(NOT TARGET ddsview)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DdsView\\.cpp")
        endif()
        if(NOT TARGET displayPanelSimulator)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_DotMatrixDisplay\\.cpp")
        endif()
        if(NOT TARGET LicenceEditor)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_LicenceEditor\\.cpp")
        endif()
        if(NOT TARGET localDomainFinder)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_LocalDomainFinder\\.cpp")
        endif()
        if(NOT TARGET LogViewer)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_LogViewer\\.cpp")
        endif()
        # Group 7 (A,B,C,E,I) exclusions
        if(NOT TARGET AdlerWebSocketSimulator)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_AdlerWebSocketSimulator\\.cpp")
        endif()
        if(NOT TARGET AsmWorkstationCertifier)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_AsmWorkstationCertifier\\.cpp")
        endif()
        if(NOT TARGET CnrProxyTester)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_CnrProxyTester\\.cpp")
        endif()
        if(NOT TARGET ConfigX)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_ConfigX\\.cpp")
        endif()
        if(NOT TARGET EEMFakeServer)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_EEMFakeServer\\.cpp")
        endif()
        if(NOT TARGET egcuSimulator)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_egcuSimulator\\.cpp")
        endif()
        # Group 8 (J,M,N,P,Q) exclusions
        if(NOT TARGET ParticipantDataGenerator)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_ParticipantDataGenerator\\.cpp")
        endif()
        if(NOT TARGET ProjectSettingsEditor)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_ProjectSettingsEditor\\.cpp")
        endif()
        if(NOT TARGET qledline)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_QLedLine\\.cpp")
        endif()
        if(NOT TARGET qledmatrix)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_QLedMatrix\\.cpp")
        endif()
        # Group 9 (R,S,T,V,W) exclusions
        if(NOT TARGET RestClientUi)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_RestClientUi\\.cpp")
        endif()
        if(NOT TARGET ScreenIdShow)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_ScreenIdShow\\.cpp")
        endif()
        if(NOT TARGET SerialToTcpConverter)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_SerialToTcpConverter\\.cpp")
        endif()
        if(NOT TARGET Splash)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_Splash\\.cpp")
        endif()
        if(NOT TARGET SqlBrowser)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_SqlBrowser\\.cpp")
        endif()
        if(NOT TARGET TextEditorTest)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_TextEditorTest\\.cpp")
        endif()
        if(NOT TARGET Times)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_Times\\.cpp")
        endif()
        if(NOT TARGET TopicDiscover)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_TopicDiscover\\.cpp")
        endif()
        if(NOT TARGET TrajectoryWidget)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_TrajectoryWidget\\.cpp")
        endif()
        if(NOT TARGET VapixConfig)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_VapixConfig\\.cpp")
        endif()
        if(NOT TARGET VideoImport)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_VideoImport\\.cpp")
        endif()
        if(NOT TARGET WlsRandomPositions)
            list(FILTER EXISTING_SOURCES EXCLUDE REGEX "test_WlsRandomPositions\\.cpp")
        endif()

        if(NOT EXISTING_SOURCES)
            message(WARNING "No migration test sources found after filtering - skipping migration_tests target")
            return()
        endif()

        add_executable(migration_tests ${EXISTING_SOURCES})

        # FLM/FLT tests include build-tree generated headers (flm_[dtc|ftc|enums],
        # flt_[dtc|ftc|enums]) - make sure codegen of these services ran first.
        if(TARGET svcFlmCommon)
            add_dependencies(migration_tests svcFlmCommon)
        endif()
        if(TARGET svcFltCommon)
            add_dependencies(migration_tests svcFltCommon)
        endif()

        # The *_dtc/*_enums tests include the rtiddsgen/codegen outputs of
        # the migrated services from ${CMAKE_BINARY_DIR}/Lts/Services. The
        # OFF-era stub copies these tests used to resolve (include/ and
        # Lts/Services source stubs) were removed, so the codegen of each
        # service must run before migration_tests compiles - the same
        # ordering the svcFlmCommon/svcFltCommon blocks above provide.
        # Nothing else in the docker_build.sh make list builds these
        # service targets, so without these deps the generated headers are
        # missing on a fresh build.
        foreach(_svc_common IN ITEMS
            svcAesCommon svcAlmCommon svcAsmCommon svcAvmCommon svcCodCommon
            svcEemCommon svcEsmCommon svcEscCommon svcEvlCommon svcExmCommon
            svcGimCommon svcIsmCommon svcMdmCommon svcMsgCommon svcMrkCommon
            svcNomCommon svcNmeCommon svcOpmCommon svcOssCommon svcPdmCommon
            svcPpmCommon
            svcPreCommon svcRepCommon svcSomCommon svcSrmCommon svcSrpCommon
            svcTgtCommon svcWhgCommon)
          if(TARGET ${_svc_common})
            add_dependencies(migration_tests ${_svc_common})
          endif()
        endforeach()

        # test_ces_dtc / test_scm_dtc include the CentralEffectSimulation and
        # ServiceManagement rtiddsgen/codegen outputs (ces_dtc.h, scm_dtc.h)
        # from build4/Lts/Services; test_cmo_dtc / test_gna_dtc include the
        # ComponentMonitor and GuezNasat outputs (cmo_dtc.h, gna_dtc.h) from
        # build4/Lts/Proxies. Same ordering requirement as the blocks above:
        # without these deps a parallel make can start migration_tests before
        # those headers exist.
        foreach(_extra_common IN ITEMS
            svcCesCommon svcCmoCommon svcGnaCommon svcScmCommon)
          if(TARGET ${_extra_common})
            add_dependencies(migration_tests ${_extra_common})
          endif()
        endforeach()

        # test_core_enums includes Lts/DDS/Core/core_enums.hpp, an rtiddsgen
        # output built by ddscore. ddscore is in the make target list, but a
        # parallel make gives no ordering between it and migration_tests.
        if(TARGET ddscore)
            add_dependencies(migration_tests ddscore)
        endif()

        # test_tab_dtc includes the TrainingAreaBase rtiddsgen/codegen
        # outputs (tab.hpp, tab_dtc.h) from build4/Lts/Proxies - same
        # ordering requirement as the service blocks above.
        if(TARGET svcTabCommon)
            add_dependencies(migration_tests svcTabCommon)
        endif()

        # test_taboc_dtc includes the TrainingAreaBaseOC outputs
        # (taboc.hpp, taboc_dtc.h) from build4/Lts/Proxies likewise.
        if(TARGET svcTabocCommon)
            add_dependencies(migration_tests svcTabocCommon)
        endif()

        # test_bld_dtc / test_bld_enums include the Buildings outputs
        # (bld.hpp, bld_dtc.h, bld_enums.hpp) from build4/Lts/Proxies
        # likewise (the CONFIGURE_FILE stub copy was removed).
        if(TARGET svcBldCommon)
            add_dependencies(migration_tests svcBldCommon)
        endif()

        # test_nme_dtc / test_nmea_handler include the server-topic
        # interfaces (nme_dts.h, nme_fts.h) that CODEGEN_SERVER_TOPICS
        # generates into the svcNmeServer target - same ordering
        # requirement as the blocks above (without it a parallel make
        # can start migration_tests before those headers exist).
        if(TARGET svcNmeServer)
            add_dependencies(migration_tests svcNmeServer)
        endif()

        # Enable Qt Meta-Object Compiler for tests with Q_OBJECT
        set_target_properties(migration_tests PROPERTIES AUTOMOC ON)
        
        target_compile_features(migration_tests PRIVATE cxx_std_17)
        
        # BEFORE: the root CMakeLists' include_directories() puts include/ early
        # on the path, so the BUILD_RTI=OFF stub variant of DDS/Generic would
        # shadow the real DDS framework headers that the generated flm/flt
        # service headers pull in — same fix the service CMakeLists enforce
        # with include_directories(BEFORE ${CMAKE_SOURCE_DIR}/Lts).
        target_include_directories(migration_tests BEFORE PRIVATE
            ${CMAKE_SOURCE_DIR}/Lts
        )
        target_include_directories(migration_tests PRIVATE
            ${CMAKE_SOURCE_DIR}
            ${CMAKE_SOURCE_DIR}/include
            ${CMAKE_BINARY_DIR}/Lts
            ${CMAKE_BINARY_DIR}/Lts/Common
            ${CMAKE_BINARY_DIR}/Lts/Common/CodeGen
            ${CMAKE_BINARY_DIR}/Lts/Common/LtsTimeline
            ${CMAKE_SOURCE_DIR}/Lts/Common/LtsTimelineClassic
            ${CMAKE_BINARY_DIR}/Lts/Services
            ${CMAKE_SOURCE_DIR}/Lts/Services
            ${CMAKE_SOURCE_DIR}/Lts/Proxies
            ${CMAKE_BINARY_DIR}/Lts/Proxies
            # Source headers under Lts/DDS/DDSConnector and
            # Lts/Common/LtsCoordTrans include their build-tree export
            # headers by bare quoted name (ddsconnector_export.h,
            # ltscoordtrans_export.h); the OFF-stub copies under include/
            # that used to satisfy those includes were removed.
            ${CMAKE_BINARY_DIR}/Lts/DDS/DDSConnector
            ${CMAKE_BINARY_DIR}/Lts/Common/LtsCoordTrans
            ${CMAKE_SOURCE_DIR}/Z/src/NGLLogger
            # Core/core_dtc.h resolves to the ddscore codegen output
            # (build-dir Lts/DDS/Core/core_dtc.h); DDS/DTC/generic_dtc.h
            # resolves to the real Lts/DDS/DTC header. Appended last so they
            # have the lowest include precedence (no shadowing).
            ${CMAKE_SOURCE_DIR}/Lts
            ${CMAKE_BINARY_DIR}/Lts/DDS
        )

        # test_flm_dtc_impl_custom.cpp includes flm_dtc_impl_custom.h, which
        # pulls in the generated flm_dtc_impl.h. Its include guard requires
        # MAKE_SVCFLMCLIENT_LIB (defined by NGL_ADD_LIBRARY on svcFlmClient,
        # which compiles flm_dtc_impl_custom.cpp).
        target_compile_definitions(migration_tests PRIVATE MAKE_SVCFLMCLIENT_LIB)

        # test_CppTopicGeneratorGrantlee.cpp bootstraps the NGL root logger
        # before constructing the generator. The <NGLLogger/...> headers
        # resolve via Z/src, the generated ngllogger_export.h via the
        # library's binary dir.
        target_include_directories(migration_tests PRIVATE
            ${CMAKE_SOURCE_DIR}/Z/src
            ${CMAKE_BINARY_DIR}/Z/src/NGLLogger
        )

        # Export-header tests locate generated headers in the build tree.
        # The directory name is not stable across pipeline stages (build4),
        # so the path is passed in instead of being hardcoded.
        target_compile_definitions(migration_tests PRIVATE MIGRATION_TEST_BUILD_DIR="${CMAKE_BINARY_DIR}")
        
        # Link against Qt6 components (Qt6::Test not needed - using gtest)
if(QT6_GUI_AVAILABLE)
          target_link_libraries(migration_tests PRIVATE
              Qt6::Core
              Qt6::Gui
              Qt6::Widgets
              GTest::gtest_main
          )
else()
          target_link_libraries(migration_tests PRIVATE
              Qt6::Core
              GTest::gtest_main
          )
endif()
        
        # Link against Z-module libraries for integration tests
        # These are the core NGL libraries migrated to Qt6
        if(TARGET NGLLogger)
            target_link_libraries(migration_tests PRIVATE NGLLogger)
        endif()
        if(TARGET ngltools)
            target_link_libraries(migration_tests PRIVATE ngltools)
        endif()
        if(TARGET ngldb)
            target_link_libraries(migration_tests PRIVATE ngldb)
        endif()
        if(TARGET nglsettings)
            target_link_libraries(migration_tests PRIVATE nglsettings)
        endif()
        if(TARGET ngltranslator)
            target_link_libraries(migration_tests PRIVATE ngltranslator)
        endif()
        if(TARGET nglcompression)
            target_link_libraries(migration_tests PRIVATE nglcompression)
        endif()
        if(TARGET tcpserver)
            target_link_libraries(migration_tests PRIVATE tcpserver)
        endif()
        if(TARGET nglapplication)
            target_link_libraries(migration_tests PRIVATE nglapplication)
        endif()
        if(TARGET qtsingleapplication)
            target_link_libraries(migration_tests PRIVATE qtsingleapplication)
        endif()
        if(TARGET wms_json_ds)
            target_link_libraries(migration_tests PRIVATE wms_json_ds)
        endif()
        if(TARGET nglwidgets AND QT6_GUI_AVAILABLE)
            target_link_libraries(migration_tests PRIVATE nglwidgets)
        endif()

        # NmeaManagement tests instantiate the generated nme types (nme.hpp
        # default ctors, ServiceControlEnum stream operator) and the service
        # logger (logger.cpp) - both compiled into svcNmeCommon.
        if(TARGET svcNmeCommon)
            target_link_libraries(migration_tests PRIVATE svcNmeCommon)
        endif()

        # FLM/FLT service tests include the Q_OBJECT custom headers of the
        # migrated services (flm_db_impl_custom.h, flm_dtc_impl_custom.h).
        # Their moc output references the generated bases' staticMetaObject
        # (DatabaseInterface, DtcImpl) defined in the service libraries.
        if(TARGET svcFlmCommon)
            target_link_libraries(migration_tests PRIVATE svcFlmCommon)
        endif()
        if(TARGET svcFlmClient)
            target_link_libraries(migration_tests PRIVATE svcFlmClient)
        endif()
        
        # Link against LtsTimelineClassic only if it exists (may not exist with MIGRATE_MODULE)
        if(TARGET LtsTimelineClassic)
            target_link_libraries(migration_tests PRIVATE LtsTimelineClassic)
            add_dependencies(migration_tests LtsTimelineClassic)
        else()
            message(STATUS "LtsTimelineClassic target not available - skipping link (MIGRATE_MODULE may restrict scope)")
        endif()
        
        # Grantlee tests require BUILD_GRANTLEE=ON
        if(BUILD_GRANTLEE)
            target_link_libraries(migration_tests PRIVATE codegen_grantlee)
            target_include_directories(migration_tests PRIVATE
                ${CMAKE_SOURCE_DIR}/Lts/Common/CodeGen
            )
            message(STATUS "Migration tests: Grantlee support enabled")
        endif()
        
        # RTI libraries if BUILD_RTI is ON
        if(BUILD_RTI)
            find_package(RTI QUIET)
            if(RTI_FOUND)
                target_include_directories(migration_tests PRIVATE ${RTI_INCLUDE_DIRS})
                target_link_libraries(migration_tests PRIVATE ${RTI_LIBRARIES})
                target_compile_definitions(migration_tests PRIVATE BUILD_RTI=1)
                message(STATUS "RTI found: ${RTI_LIBRARIES}")
            else()
                message(STATUS "BUILD_RTI=ON but RTI not found - building tests without RTI")
            endif()
        endif()
        
        # Register with CTest
        include(GoogleTest)
        gtest_discover_tests(migration_tests)
        
        message(STATUS "Migration tests enabled: ${EXISTING_SOURCES}")
    else()
        message(WARNING "No migration test sources found in ${CMAKE_CURRENT_SOURCE_DIR}")
    endif()
endif()