#
# Haupt CMakeLists.txt für das Projekt TDS
#
# $Id$
# $HeadURL$
# $Author$
#
# Setzen von CMAKE_INSTALL_PREFIX auf "/shd/CTC" falls nicht über Kommandozeile angegeben
#

CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
IF(POLICY CMP0069)
  CMAKE_POLICY(SET CMP0069 NEW) # cmake >= 3.9.0 - INTERPROCEDURAL_OPTIMIZATION behavior
ENDIF()
IF(POLICY CMP0071)
  CMAKE_POLICY(SET CMP0071 NEW) # cmake >= 3.10.0 - automatically process generated sources with AUTOMOC
ENDIF()
IF(POLICY CMP0072)
  CMAKE_POLICY(SET CMP0072 NEW) # cmake >= 3.11.0 - prefer libOpenGL.so over legacy libGL.so
ENDIF()


IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
  SET(CMAKE_INSTALL_PREFIX "/shd/CTC" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
ENDIF()
#
# # Setzen von CMAKE_BUILD_TYPE auf "Debug" falls nicht über Kommandozeile angegeben
#
IF(NOT DEFINED CMAKE_BUILD_TYPE)
  SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
ENDIF()
ADD_DEFINITIONS(-DEXPORT_BDV_TOPIC_AS_JSON)
SET(_ver "1.2.0")
IF(DEFINED LTS_VERSION_MAJOR AND DEFINED LTS_VERSION_MINOR AND DEFINED LTS_VERSION_PATCH)
  SET(_ver "${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
ENDIF()
PROJECT(LTS VERSION ${_ver})
MESSAGE(STATUS "LTS Version: ${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")

# Enable CTest integration for unit tests
include(CTest)

# Release scope: subdirectories are added unconditionally (no per-module migration builds)
function(NGL_ADD_SUBDIR_GUARDED subdir)
  add_subdirectory(${subdir})
endfunction()

SET(LTS_VERSION_DATE  "01.01.2018" CACHE STRING "The date when this software was compiled")
ADD_DEFINITIONS(-DLTS_VERSION_MAJOR=\"${LTS_VERSION_MAJOR}\")
ADD_DEFINITIONS(-DLTS_VERSION_MINOR=\"${LTS_VERSION_MINOR}\")
ADD_DEFINITIONS(-DLTS_VERSION_PATCH=\"${LTS_VERSION_PATCH}\")
ADD_DEFINITIONS(-DLTS_VERSION_DATE=\"${LTS_VERSION_DATE}\")
IF(JENKINS_BUILD_NUMBER)
  ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"${JENKINS_BUILD_NUMBER}\")
ELSE()
  ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"unknown\")
ENDIF()

ADD_DEFINITIONS(-DAPP6C)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
# Resolve <DDS/...> and other framework includes to the real headers under
# Lts/ BEFORE the migration stub tree in include/. The stub tree shadows them
# otherwise and opens namespace DDSGeneric around framework includes, which
# pulls Qt/std definitions into that namespace and breaks every consumer.
# (The qt5 legacy has no include/ tree; Lts/ is the real include root.)
include_directories(BEFORE ${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)
# Include directory for generated export headers
include_directories(${CMAKE_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/Z/src)
# Include directories for external dependencies and internal modules
include_directories(${CMAKE_SOURCE_DIR}/Z/src)
include_directories(${CMAKE_SOURCE_DIR}/Z/src/ngltools)
# Lts/Viewer is outside the release scope; only add the include paths when
# present to avoid -Wmissing-include-dirs warnings on validation-scope trees
if(EXISTS "${CMAKE_SOURCE_DIR}/Lts/Viewer/SituationMap/Symbology")
  include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/SituationMap/Symbology)
  include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/LtsDataView)
endif()
include_directories(${CMAKE_SOURCE_DIR}/Lts/Proxies/TrainingAreaBase)
# Release scope: include path for ProjectDataManagement stub headers
IF(RELEASE_BUILD)
  include_directories(${CMAKE_SOURCE_DIR}/Lts/Services/ProjectDataManagement/stubs)
ENDIF()
include_directories(${CMAKE_SOURCE_DIR}/Lts/Common)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Common/LtsUtils)
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsCore)
# LtsUtilsSettings's generated ltsutilssettings_export.h is included by bare name from
# settings.h. Consumer targets that reach settings.h transitively (without linking
# LtsUtilsSettings themselves) cannot see it through the target's PUBLIC interface, so the
# directory holding the generated header has to be visible tree-wide. The directory contains
# only that generated header, so appending it cannot shadow an existing include.
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsSettings)
include_directories(${CMAKE_SOURCE_DIR}/Z/src/NGLLogger)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Qt6 Migration: Removed CMAKE_POSITION_INDEPENDENT_CODE - Qt6 handles PIC automatically
# and this setting conflicts with Qt6's reduce_relocations feature
# SET(CMAKE_POSITION_INDEPENDENT_CODE ON)

IF(CMAKE_VERSION VERSION_GREATER 3.15.9)
  OPTION(USE_UNITY_BUILDS "Use Unity builds to speed up compilation (cmake 3.16 or newer required!)" OFF)
  IF (USE_UNITY_BUILDS)
    SET(CMAKE_UNITY_BUILD ON)
    SET(CMAKE_UNITY_BUILD_BATCH_SIZE 40)
  ENDIF()
ENDIF()

# Add Lts/ include path globally for QosProfile and other Lts headers
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/Lts)

OPTION(BUILD_LTSWEBSOCKET "Build LtsWebSocket module (requires NGLLogger)" ON)

# Set CMAKE_MODULE_PATH early so FIND_PACKAGE can find our custom Find modules
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
INCLUDE(FindLibraryWithDebug)

ENABLE_TESTING()
INCLUDE(CTest)
CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY)
CONFIGURE_FILE(lts-cc.conf ${CMAKE_BINARY_DIR}/lts-cc.conf.distrib COPYONLY)

# Add bundled GeographicLib cmake config to find modern targets (GeographicLib::GeographicLib_SHARED)
LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/include/GeographicLib/lib/cmake")
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
IF(WIN32)
  SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
ELSE(WIN32)
  SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
ENDIF()

#
# Disallow in-source build
#
INCLUDE(MacroEnsureOutOfSourceBuild)

macro_ensure_out_of_source_build("In-Source build nicht erlaubt!")

#
# Qt ist wichtig - zuerst suchen
#
SET(CMAKE_AUTOMOC TRUE)
SET(CMAKE_AUTOUIC TRUE)
SET(QT_USE_IMPORTED_TARGETS TRUE)

# Check for OpenGL first (required by Qt6Gui)
find_package(OpenGL)

# Prefer Qt6, fallback to Qt5. Create Qt6::*-aliases when Qt6 is found so existing CMakeLists continue to work.
# Try to find Qt6 with GUI components first
set(QT6_GUI_AVAILABLE FALSE)
set(QT6_FOUND FALSE)
set(QT6_CORE5COMPAT_AVAILABLE FALSE)

# First check if Core5Compat is available
find_package(Qt6 6.2 COMPONENTS Core5Compat QUIET)
if(Qt6Core5Compat_FOUND)
  set(QT6_CORE5COMPAT_AVAILABLE TRUE)
  message(STATUS "Found Qt6Core5Compat")
endif()

# Find Qt6 core components first (without OpenGL which may not be available)
# WebSockets is required by the migrated services (FileManagement's THP script
# server uses QWebSocketServer; LtsWebSocket/httq enable their real websocket
# paths via QT6_WEBSOCKETS_AVAILABLE when the module is found).
find_package(Qt6 6.2 COMPONENTS Concurrent Core LinguistTools Network
  Multimedia Sql SerialPort Test Xml Positioning Svg WebSockets PrintSupport OpenGL QUIET)

if(Qt6_FOUND)
  # Check if OpenGL was found (GUI support available)
  if(OpenGL_FOUND)
    set(QT6_GUI_AVAILABLE TRUE)
    message(STATUS "Found Qt6 with GUI support (OpenGL): ${Qt6Core_VERSION}")
  else()
    # Skip GUI find_package - it fails without OpenGL. We'll create manual targets below.
    set(QT6_GUI_AVAILABLE FALSE)
    message(STATUS "Found Qt6 (GUI will be manually configured): ${Qt6Core_VERSION}")
  endif()
endif()

# If Qt6 not found yet, try with full component list including OpenGL
if(NOT Qt6_FOUND)
  find_package(Qt6 6.2 COMPONENTS Concurrent Core LinguistTools Network OpenGL PrintSupport
    Multimedia Sql Svg SerialPort Test UiTools WebSockets WebEngineCore WebEngineWidgets
    Widgets Xml Positioning QUIET)
  if(Qt6_FOUND AND OpenGL_FOUND)
    set(QT6_GUI_AVAILABLE TRUE)
    message(STATUS "Found Qt6 with GUI support (OpenGL): ${Qt6Core_VERSION}")
  endif()
endif()

if(NOT Qt6_FOUND)
  # Final fallback - try to find Qt6 with minimum required components
  find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
  message(STATUS "Found Qt6 (minimal): ${Qt6Core_VERSION}")
endif()

# Manual Qt6 configuration - create imported targets for available libraries
if(NOT TARGET Qt6::Core)
  find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
endif()

# Create imported targets for all available Qt6 libraries
# Use Qt6 installation path from find_package or fall back to system paths
if(Qt6Core_DIR)
  # <Qt6Core_DIR> is the cmake package dir: <prefix>/lib/cmake/Qt6Core in the
  # standard Qt layout and <prefix>/<multiarch>/cmake/Qt6Core in the Debian/
  # Ubuntu layout — so the library dir is two levels up in both. (Going three
  # levels up and appending /lib only matches the standard layout; in the
  # Debian validation container it resolved to /usr/lib/lib and every manual
  # target below was silently skipped, breaking all targets linking
  # Qt6::Sql / Qt6::Xml / Qt6::Test.)
  get_filename_component(QT6_LIB_DIR "${Qt6Core_DIR}/../.." ABSOLUTE)
  get_filename_component(QT6_ARCH_DIR "${QT6_LIB_DIR}" NAME)
  # The standard layout keeps headers in <prefix>/include; Debian/Ubuntu keeps
  # them in <prefix>/include/<multiarch>/qt6 — probe the multiarch form first.
  if(EXISTS "${QT6_LIB_DIR}/../../include/${QT6_ARCH_DIR}/qt6")
    get_filename_component(QT6_INC_DIR "${QT6_LIB_DIR}/../../include/${QT6_ARCH_DIR}/qt6" ABSOLUTE)
  else()
    get_filename_component(QT6_INC_DIR "${QT6_LIB_DIR}/../include" ABSOLUTE)
  endif()
elseif(DEFINED ENV{QT_BASE_DIR} AND DEFINED ENV{QT_VERSION} AND DEFINED ENV{QT_ARCH_DIR})
  set(QT6_LIB_DIR "$ENV{QT_BASE_DIR}/$ENV{QT_VERSION}/$ENV{QT_ARCH_DIR}/lib")
  set(QT6_INC_DIR "$ENV{QT_BASE_DIR}/$ENV{QT_VERSION}/$ENV{QT_ARCH_DIR}/include")
else()
  set(QT6_LIB_DIR "/usr/lib/x86_64-linux-gnu")
  set(QT6_INC_DIR "/usr/include/x86_64-linux-gnu/qt6")
endif()

# Qt6::DBus
if(NOT TARGET Qt6::DBus AND EXISTS "${QT6_LIB_DIR}/libQt6DBus.so.6")
  add_library(Qt6::DBus SHARED IMPORTED)
  set_target_properties(Qt6::DBus PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6DBus.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtDBus;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core"
  )
endif()

# Qt6::Gui (needs OpenGL libs, X11, EGL)
if(NOT TARGET Qt6::Gui AND EXISTS "${QT6_LIB_DIR}/libQt6Gui.so.6")
  add_library(Qt6::Gui SHARED IMPORTED)
  set_target_properties(Qt6::Gui PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Gui.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtGui;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::DBus;${QT6_LIB_DIR}/libQt6OpenGL.so.6;${QT6_LIB_DIR}/libEGL.so.1;${QT6_LIB_DIR}/libGLX.so.0;${QT6_LIB_DIR}/libX11.so.6;${CMAKE_DL_LIBS};pthread"
  )
endif()

# Set variable for legacy code that uses ${Qt6_Gui} — like Qt6_Widgets below,
# subdirectory CMakeLists contain `set(Qt6_Gui ${Qt6_Gui})` optional-guard
# no-ops that keep this root-scope value.
if(TARGET Qt6::Gui)
  set(Qt6_Gui Qt6::Gui)
endif()

# Qt6::Widgets - create manual target (find_package fails without OpenGL)
if(EXISTS "${QT6_LIB_DIR}/libQt6Widgets.so.6")
  if(NOT TARGET Qt6::Widgets)
    add_library(Qt6::Widgets SHARED IMPORTED)
  endif()
  set_target_properties(Qt6::Widgets PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/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::Core;Qt6::Gui"
  )
  # Set variable for legacy code that uses ${Qt6_Widgets}
  set(Qt6_Widgets Qt6::Widgets)
  set(QT6_GUI_AVAILABLE TRUE)
  message(STATUS "Manually configured Qt6 Widgets target")
endif()

# Qt6::Sql - create manual target if not found
if(NOT TARGET Qt6::Sql AND EXISTS "${QT6_LIB_DIR}/libQt6Sql.so.6")
  add_library(Qt6::Sql SHARED IMPORTED)
  set_target_properties(Qt6::Sql PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Sql.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSql;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core"
  )
  message(STATUS "Manually configured Qt6 Sql target")
endif()

# Qt6::Xml - create manual target if not found
if(NOT TARGET Qt6::Xml AND EXISTS "${QT6_LIB_DIR}/libQt6Xml.so.6")
  add_library(Qt6::Xml SHARED IMPORTED)
  set_target_properties(Qt6::Xml PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Xml.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtXml;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core"
  )
  message(STATUS "Manually configured Qt6 Xml target")
endif()

# Qt6::Network - create manual target if not found
if(NOT TARGET Qt6::Network AND EXISTS "${QT6_LIB_DIR}/libQt6Network.so.6")
  add_library(Qt6::Network SHARED IMPORTED)
  set_target_properties(Qt6::Network PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Network.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtNetwork;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core"
  )
  message(STATUS "Manually configured Qt6 Network target")
endif()

# Qt6::Test - create manual target if not found
if(NOT TARGET Qt6::Test AND EXISTS "${QT6_LIB_DIR}/libQt6Test.so.6")
  add_library(Qt6::Test SHARED IMPORTED)
  set_target_properties(Qt6::Test PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Test.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtTest;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core"
  )
  message(STATUS "Manually configured Qt6 Test target")
endif()

# Qt6::Multimedia - create manual target if not found
if(NOT TARGET Qt6::Multimedia AND EXISTS "${QT6_LIB_DIR}/libQt6Multimedia.so.6")
  add_library(Qt6::Multimedia SHARED IMPORTED)
  set_target_properties(Qt6::Multimedia PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Multimedia.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtMultimedia;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
  )
  message(STATUS "Manually configured Qt6 Multimedia target")
endif()

# Stub Qt6::Multimedia target if not available (needed by OscSystemGuiPlugin, etc.)
if(NOT TARGET Qt6::Multimedia)
  add_library(Qt6::Multimedia INTERFACE IMPORTED)
  set_target_properties(Qt6::Multimedia PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_MULTIMEDIA"
  )
  message(STATUS "Created stub target for Qt6::Multimedia (library not available)")
endif()

# Qt6::Svg - create manual target if not found. Also require the headers:
# the container can ship the runtime library (libqt6svg6 via Recommends)
# without qt6-svg-dev, and an imported target with a non-existent
# INTERFACE_INCLUDE_DIRECTORIES entry fails the CMake generate step for
# every Svg consumer. Without headers the stub below is used instead.
if(NOT TARGET Qt6::Svg AND EXISTS "${QT6_LIB_DIR}/libQt6Svg.so.6" AND EXISTS "${QT6_INC_DIR}/QtSvg")
  add_library(Qt6::Svg SHARED IMPORTED)
  set_target_properties(Qt6::Svg PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Svg.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSvg;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
  )
  message(STATUS "Manually configured Qt6 Svg target")
endif()

# Stub Qt6::Svg target if not available (needed by various plugins)
if(NOT TARGET Qt6::Svg)
  add_library(Qt6::Svg INTERFACE IMPORTED)
  message(STATUS "Created stub target for Qt6::Svg (library not available)")
endif()

# Qt6::SerialPort - create manual target if not found
if(NOT TARGET Qt6::SerialPort AND EXISTS "${QT6_LIB_DIR}/libQt6SerialPort.so.6")
  add_library(Qt6::SerialPort SHARED IMPORTED)
  set_target_properties(Qt6::SerialPort PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6SerialPort.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSerialPort;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core"
  )
  message(STATUS "Manually configured Qt6 SerialPort target")
endif()

# Stub Qt6::SerialPort target if not available (needed by TrainingAreaBaseOC)
if(NOT TARGET Qt6::SerialPort)
  add_library(Qt6::SerialPort INTERFACE IMPORTED)
  set_target_properties(Qt6::SerialPort PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_SERIALPORT"
  )
  message(STATUS "Created stub target for Qt6::SerialPort (library not available)")
endif()

# Stub Qt6::WebEngineCore target if not available (needed by thp_viewer)
if(NOT TARGET Qt6::WebEngineCore)
  add_library(Qt6::WebEngineCore INTERFACE IMPORTED)
  set_target_properties(Qt6::WebEngineCore PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBENGINE"
  )
  message(STATUS "Created stub target for Qt6::WebEngineCore (library not available)")
endif()

# Stub Qt6::WebEngineWidgets target if not available (needed by thp_viewer)
if(NOT TARGET Qt6::WebEngineWidgets)
  add_library(Qt6::WebEngineWidgets INTERFACE IMPORTED)
  set_target_properties(Qt6::WebEngineWidgets PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBENGINE"
  )
  message(STATUS "Created stub target for Qt6::WebEngineWidgets (library not available)")
endif()

# Stub Qt6::Core5Compat target if not available (needed by textEditorTest)
if(NOT TARGET Qt6::Core5Compat)
  add_library(Qt6::Core5Compat INTERFACE IMPORTED)
  set_target_properties(Qt6::Core5Compat PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_CORE5COMPAT"
  )
  message(STATUS "Created stub target for Qt6::Core5Compat (library not available)")
endif()

# Qt6::WebSockets - create manual target if not found (the container's Qt6
# discovery takes the minimal path, so find_package never creates the
# component targets). The migrated FileManagement service (THP script
# server) needs the real module.
if(NOT TARGET Qt6::WebSockets AND EXISTS "${QT6_LIB_DIR}/libQt6WebSockets.so.6")
  add_library(Qt6::WebSockets SHARED IMPORTED)
  set_target_properties(Qt6::WebSockets PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6WebSockets.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtWebSockets;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Network"
  )
  set(QT6_WEBSOCKETS_REAL_FOUND TRUE)
  message(STATUS "Manually configured Qt6 WebSockets target")
endif()

# Stub Qt6::WebSockets target if not available (needed by LtsWebSocket, httq, etc.)
if(NOT TARGET Qt6::WebSockets)
  add_library(Qt6::WebSockets INTERFACE IMPORTED)
  set_target_properties(Qt6::WebSockets PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBSOCKETS"
  )
  message(STATUS "Created stub target for Qt6::WebSockets (library not available)")
endif()

# Qt6::PrintSupport - create manual target if not found
if(NOT TARGET Qt6::PrintSupport AND EXISTS "${QT6_LIB_DIR}/libQt6PrintSupport.so.6")
  add_library(Qt6::PrintSupport SHARED IMPORTED)
  set_target_properties(Qt6::PrintSupport PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6PrintSupport.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtPrintSupport;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui;Qt6::Widgets"
  )
  message(STATUS "Manually configured Qt6 PrintSupport target")
endif()

# Stub Qt6::PrintSupport target if not available (needed by textEditorTest, thp_viewer)
if(NOT TARGET Qt6::PrintSupport)
  add_library(Qt6::PrintSupport INTERFACE IMPORTED)
  set_target_properties(Qt6::PrintSupport PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_PRINTSUPPORT"
  )
  message(STATUS "Created stub target for Qt6::PrintSupport (library not available)")
endif()

# Qt6::OpenGL - create manual target if not found
if(NOT TARGET Qt6::OpenGL AND EXISTS "${QT6_LIB_DIR}/libQt6OpenGL.so.6")
  add_library(Qt6::OpenGL SHARED IMPORTED)
  set_target_properties(Qt6::OpenGL PROPERTIES
    IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6OpenGL.so.6"
    INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtOpenGL;${QT6_INC_DIR}"
    INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
  )
  message(STATUS "Manually configured Qt6 OpenGL target")
endif()

# Stub Qt6::OpenGL target if not available (needed by PwsGuiPlugin)
if(NOT TARGET Qt6::OpenGL)
  add_library(Qt6::OpenGL INTERFACE IMPORTED)
  set_target_properties(Qt6::OpenGL PROPERTIES
    INTERFACE_COMPILE_DEFINITIONS "QT_NO_OPENGL"
  )
  message(STATUS "Created stub target for Qt6::OpenGL (library not available)")
endif()

# Set variable for legacy code that uses ${Qt6_WebSockets} — subdirectory
# CMakeLists contain `set(Qt6_WebSockets ${Qt6_WebSockets})` optional-guard
# no-ops that keep this root-scope value.
if(TARGET Qt6::WebSockets)
  set(Qt6_WebSockets Qt6::WebSockets)
endif()

# The real Qt6 WebSockets module is available (either via find_package or the
# manual import above): enable the real websocket code paths in httq,
# LtsWebSocket and the migrated services (they check this macro; without it
# they fall back to websocket-less operation).
if(Qt6WebSockets_FOUND OR QT6_WEBSOCKETS_REAL_FOUND)
  add_compile_definitions(QT6_WEBSOCKETS_AVAILABLE)
endif()

MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}, GUI available: ${QT6_GUI_AVAILABLE}")

#
ADD_DEFINITIONS(-DQT_USE_QSTRINGBUILDER)
ADD_DEFINITIONS(-DQT_NO_CAST_TO_ASCII)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_ASCII)
ADD_DEFINITIONS(-DQT_NO_URL_CAST_FROM_STRING)
ADD_DEFINITIONS(-DQT_DEPRECATED_WARNINGS)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_BYTEARRAY)
#ADD_DEFINITIONS(-DQT_NO_DEPRECATED)
ADD_DEFINITIONS(-DQT_DISABLE_DEPRECATED_BEFORE=0x050900)
ADD_DEFINITIONS(-DQT_NO_FOREACH)
IF(NOT WIN32)
  ADD_DEFINITIONS(-DQT_STRICT_ITERATORS)
ENDIF()

#
# Ein paar NGL-spezifische Macros
#
INCLUDE(NGLMacros)

#
# Projektspezifische Einstellungen?
#
NGL_INSTALL(SV AAR WS FILES lts-cc.conf DESTINATION . RENAME lts-cc.conf.distrib)

OPTION(GUEZ_MODE "Build for GUEZ " ON)
IF(GUEZ_MODE)
  ADD_DEFINITIONS(-DGUEZ_MODE)
ENDIF()

#
# Doxygen
#
INCLUDE(DoxygenMacros)
IF(NOT DOXYGEN_OUT_DIR)
  SET(DOXYGEN_OUT_DIR ${CMAKE_BINARY_DIR}/doxygen)
ENDIF()
ADD_DOXYGEN_TARGET(TDS ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile
                       ${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
                       ${DOXYGEN_OUT_DIR})

IF(NOT DOXYGEN_OUT_DIR_2025)
  SET(DOXYGEN_OUT_DIR_2025 ${CMAKE_BINARY_DIR}/doxygen2025)
ENDIF()
ADD_DOXYGEN_TARGET(TDS2025 ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile2025.in ${CMAKE_BINARY_DIR}/Doxyfile
                           ${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
                           ${DOXYGEN_OUT_DIR_2025})

#
# Compilerflags
#
IF(WIN32)
  ADD_DEFINITIONS(-DWIN32 -D_USE_MATH_DEFINES -D_WIN32_WINNT=0x0501 -DUNICODE)
ELSE()
  ADD_DEFINITIONS(-D_LINUX)
ENDIF()

IF(MSVC)
  # C4250: 'class1' : inherits 'class2::member' via dominance
  # C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
  # C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
  # C4496: 'function': was declared deprecated
  # C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data
  ADD_DEFINITIONS(-wd4250
                  -wd4251
                  -wd4290
                  -wd4496
                  -wd4267
                  -D_CRT_SECURE_NO_DEPRECATE
                  -D_CRT_NONSTDC_NO_DEPRECATE
                  -D_SCL_SECURE_NO_WARNINGS
                  -D_WINSOCK_DEPRECATED_NO_WARNINGS
                  /bigobj
                  )
  # komplette Programmoptimierung
  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} /MP")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
  # .pdb - Datei nicht gefunden
  SET(CMAKE_EXE_LINKER_FLAGS    "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4099")
  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4099")
  # min() und max() nicht als Macros
  ADD_DEFINITIONS(-DNOMINMAX)
  SET(CMAKE_MSVCIDE_RUN_PATH "" CACHE PATH "Run path to use when starting programs from MSVC")
ENDIF()

IF(UNIX)
  # Alle Warnungen aktivieren
  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -Wall")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -Wmissing-include-dirs")
  # disable
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overloaded-virtual")
  IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.0)
      MESSAGE(FATAL_ERROR "gcc 4.8 or higher is required to build TDS: ${CMAKE_CXX_COMPILER_VERSION}")
    ENDIF()
    IF(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.99)
      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")
#      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-attribute=const")
#      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-types")
#      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-methods")
#      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
    ENDIF()
  ENDIF()
ENDIF()

OPTION(USE_IPO "Use interprocedural optimizations (cmake 3.9 or higher required)" OFF)
IF (USE_IPO AND CMAKE_VERSION VERSION_GREATER 3.8.9)
  INCLUDE(CheckIPOSupported)
  check_ipo_supported(RESULT result OUTPUT output)
  IF(result)
    SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
  ELSE()
    MESSAGE(WARNING "IPO is not supported: ${output}")
  ENDIF()
ENDIF()

OPTION(USE_ASAN "Use Address Sanitizer (current Clang only)" OFF)
IF (USE_ASAN)
  IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    MESSAGE(STATUS "enable Address Sanitizer with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
    SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
  ELSE()
    MESSAGE(STATUS "Address Sanitizer only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
  ENDIF()
ENDIF(USE_ASAN)

OPTION(USE_UBSAN "Use UndefinedBehavior Sanitizer (current Clang only)" OFF)
IF (USE_UBSAN)
  IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
    SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fsanitize=undefined")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
  ELSE()
    MESSAGE(STATUS "UndefinedBehavior only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
  ENDIF()
ENDIF(USE_UBSAN)

OPTION(BUILD_RPM "Build a RPM - install script in scripts subdir" OFF)

# Build component options for NGL_ADD_LIBRARY
OPTION(BUILD_ALL "Build all components" ON)
OPTION(BUILD_SV "Build SV component" ON)
OPTION(BUILD_WS "Build WS component" ON)
OPTION(BUILD_AAR "Build AAR component" ON)
OPTION(BUILD_TOOLSWS "Build TOOLSWS component" ON)
OPTION(BUILD_TOOLSSV "Build TOOLSSV component" ON)
OPTION(BUILD_HLA "Build HLA component" ON)

# If BUILD_ALL is ON, enable all individual component flags
IF(BUILD_ALL)
  SET(BUILD_SV ON CACHE BOOL "Build SV component" FORCE)
  SET(BUILD_WS ON CACHE BOOL "Build WS component" FORCE)
  SET(BUILD_AAR ON CACHE BOOL "Build AAR component" FORCE)
  SET(BUILD_TOOLSWS ON CACHE BOOL "Build TOOLSWS component" FORCE)
  SET(BUILD_TOOLSSV ON CACHE BOOL "Build TOOLSSV component" FORCE)
  SET(BUILD_HLA ON CACHE BOOL "Build HLA component" FORCE)
ENDIF()

IF(BUILD_RPM)
  ADD_SUBDIRECTORY(scripts)
ELSE()
  ADD_DEFINITIONS(-DLTS_DEBUG)
ENDIF()

IF (NOT DEFINED _pname)
 IF(GUEZ_MODE)
   SET (_pname "guez")
   ADD_DEFINITIONS(-DPROJECTBUILD="guez")
    MESSAGE(STATUS "NO ProjectName givin! BUT GUEZ_MODE set PROJECTBUILD to guez")
  ELSE()
    MESSAGE(WARNING "NO ProjectName givin! Can't install coresponding lts-cc.conf! and PROJECTBUILD is empty")
    ADD_DEFINITIONS(-DPROJECTBUILD="")
  ENDIF()
ELSE()
    MESSAGE(STATUS "ProjectName givin! PROJECTBUILD is ${_pname} ")
    ADD_DEFINITIONS(-DPROJECTBUILD=\"${_pname}\")
ENDIF()


# Release scope: always build only TetraIF, Z/src, and Lts/Common
# (TrainingAreaBase is included via Lts/Proxies when Lts is processed)
NGL_ADD_SUBDIR_GUARDED(TetraIF)
NGL_ADD_SUBDIR_GUARDED(Z/src)
NGL_ADD_SUBDIR_GUARDED(Lts)

# at last, to make sure we get all targets in NGL_TS_TARGETS property
NGL_ADD_SUBDIR_GUARDED(translations)
#-----------------------------------------------------------------------------------------------------
