cmake_minimum_required(VERSION 3.19)
project(soft_bus_daemon
    LANGUAGES CXX
    VERSION 1.0.0
)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")

# Output layout
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/plugins)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/plugins)

# 启用AddressSanitizer（仅在非Windows平台上） 
if(NOT WIN32)
    set(SANITIZE_FLAGS "-fsanitize=address")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
else()
    message(STATUS "AddressSanitizer disabled on Windows because the runtime is unavailable in the MinGW kit.")
endif()

# 设置C++标准
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOMOC ON)
# 查找Qt6（守护进程只需要 Core/DBus/Network/SerialPort/Sql）
find_package(Qt6 6.5 REQUIRED COMPONENTS Core SerialPort Network Sql DBus)
include(CheckIncludeFileCXX)

# 检测编译平台
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
    set(PlatformDir "x86")
else()
    set(PlatformDir "x64")
endif()

qt_standard_project_setup()

# 添加软总线模板库
# 1. 日志库
qt_add_library(softbus_template
    src/utils/logs/logging.h
    src/utils/logs/LogStream.h
)

qt_add_executable(softbus_daemon
    main.cpp
    src/core/CoreService.cpp




    # api 接口

    src/api/ipc_dbus/IpcDBus.h
    src/api/ipc_dbus/IpcDBus.cpp

    # device types
    src/devices/DeviceTypes.h
    src/devices/DeviceTypes.cpp

    # hardware interfaces (Level 2)
    src/hardware/interfaces/IStreamDriver.h
    src/hardware/interfaces/IFrameDriver.h
    src/hardware/interfaces/IDeviceWatcher.h

    # hardware drivers (Level 2)
    src/hardware/drivers/serial/SerialQtDriver.h
    src/hardware/drivers/serial/SerialQtDriver.cpp
    src/hardware/drivers/serial/SerialCapabilities.h

    # device bus: tree & capabilities
    src/device_bus/tree/DeviceTreeModel.h
    src/device_bus/tree/DeviceTreeModel.cpp

    # device bus: monitor
    src/device_bus/monitor/DeviceEvent.h
    src/device_bus/monitor/IDeviceMonitor.h
    src/device_bus/monitor/DeviceMonitorService.h
    src/device_bus/monitor/DeviceMonitorService.cpp
    src/device_bus/monitor/UdevDeviceMonitor.h
    src/device_bus/monitor/UdevDeviceMonitor.cpp
    src/device_bus/monitor/NetlinkDeviceMonitor.h
    src/device_bus/monitor/NetlinkDeviceMonitor.cpp
    src/device_bus/monitor/WindowsDeviceMonitor.h
    src/device_bus/monitor/WindowsDeviceMonitor.cpp


    # device bus: facade & manager
    src/device_bus/DeviceBus.h
    src/device_bus/DeviceBus.cpp
    src/device_bus/manager/DeviceBusManager.h
    src/device_bus/manager/DeviceBusManager.cpp
    src/device_bus/manager/SerialDeviceManager.h
    src/device_bus/manager/SerialDeviceManager.cpp

    # device bus: registry skeleton
    src/device_bus/registry/IDeviceRegistry.h
    src/device_bus/registry/DeviceRegistry.h
    src/device_bus/registry/DeviceRegistry.cpp

    # devices: base skeleton
    src/devices/base/IDevice.h
    src/devices/base/IPhysicalDevice.h

    # devices: physical
    src/devices/physical/SerialDevice.h
    src/devices/physical/SerialDevice.cpp

    # core memory/plugin
    src/core/memory/MemoryPool.h
    src/core/memory/LockFreeQueue.h
    src/core/plugin_system/IProtocolPlugin.h
    src/core/plugin_system/PluginManager.h
    src/core/plugin_system/PluginManager.cpp
    src/message_bus/pipeline/protocol/modbusrtu/ModbusRtuProtocolPlugin.h
    src/message_bus/pipeline/protocol/modbusrtu/ModbusRtuProtocolPlugin.cpp
    src/core/models/Types.h
    src/core/models/MetadataDef.h
    src/core/models/DataMapping.h
    src/core/models/DOMMessage.h
    src/core/metadata/MetadataRegistry.h
    src/core/metadata/MetadataRegistry.cpp
    src/core/metadata/ProfileRegistry.h
    src/core/metadata/ProfileRegistry.cpp

    # message bus pipeline
    src/message_bus/pipeline/PayloadRef.h
    src/message_bus/pipeline/PipelineContext.h
    src/message_bus/pipeline/PipelineEngine.h
    src/message_bus/pipeline/PipelineEngine.cpp
    src/message_bus/pipeline/protocol/ProtocolEnvelope.h
    src/message_bus/pipeline/protocol/modbusrtu/ModbusRtuPdu.h
    src/message_bus/pipeline/protocol/modbusrtu/ModbusRtuCodec.h
    src/message_bus/pipeline/protocol/modbusrtu/ModbusRtuCodec.cpp
    src/message_bus/pipeline/stages/1_framers/IFramer.h
    src/message_bus/pipeline/stages/1_framers/ModbusRtuFraming.h
    src/message_bus/pipeline/stages/1_framers/ModbusRtuFraming.cpp
    src/message_bus/pipeline/stages/1_framers/ModbusRtuFramer.h
    src/message_bus/pipeline/stages/1_framers/ModbusRtuFramer.cpp
    src/message_bus/pipeline/stages/1_framers/PassthroughFramer.h
    src/message_bus/pipeline/stages/1_framers/PassthroughFramer.cpp
    src/message_bus/pipeline/stages/2_parsers/IParserStage.h
    src/message_bus/pipeline/stages/3_filters/IFilterStage.h
    src/message_bus/pipeline/stages/3_filters/ProtocolParseFilter.h
    src/message_bus/pipeline/stages/3_filters/ProtocolParseFilter.cpp
    src/message_bus/pipeline/stages/4_validators/IValidator.h

    # message bus ingress/egress
    src/message_bus/ingress/IIngressPort.h
    src/message_bus/ingress/DriverIngressAdapter.h
    src/message_bus/ingress/DriverIngressAdapter.cpp
    src/message_bus/egress/IEgressPort.h
    src/message_bus/egress/EgressRouter.h
    src/message_bus/egress/EgressRouter.cpp
)

target_include_directories(softbus_daemon
    PRIVATE
        ${CMAKE_SOURCE_DIR}
        ${CMAKE_SOURCE_DIR}/src
)



target_link_libraries(softbus_daemon
    PRIVATE
        Qt::Core
        Qt6::DBus
        Qt6::SerialPort
        Qt6::Network
)

# Platform-specific deps
if(UNIX AND NOT APPLE)
    find_package(PkgConfig QUIET)
    if(PkgConfig_FOUND)
        pkg_check_modules(UDEV QUIET libudev)
    endif()

    if(UDEV_FOUND)
        target_include_directories(softbus_daemon PRIVATE ${UDEV_INCLUDE_DIRS})
        target_link_directories(softbus_daemon PRIVATE ${UDEV_LIBRARY_DIRS})
        target_link_libraries(softbus_daemon PRIVATE ${UDEV_LIBRARIES})
    else()
        # Fallback: rely on system linker search path
        target_link_libraries(softbus_daemon PRIVATE udev)
    endif()
endif()

if(WIN32)
    target_link_libraries(softbus_daemon PRIVATE setupapi iphlpapi user32 advapi32)
endif()

add_subdirectory(plugins)

option(SOFTBUS_BUILD_TESTS "Build unit tests" OFF)
if(SOFTBUS_BUILD_TESTS)
    find_package(Qt6 6.5 REQUIRED COMPONENTS Test)
    qt_add_executable(softbus_modbus_rtu_framer_test
        tests/modbus_rtu_framer_test.cpp
        src/message_bus/pipeline/stages/1_framers/ModbusRtuFraming.cpp
        src/message_bus/pipeline/stages/1_framers/ModbusRtuFramer.cpp
    )
    target_include_directories(softbus_modbus_rtu_framer_test PRIVATE
        ${CMAKE_SOURCE_DIR}
        ${CMAKE_SOURCE_DIR}/src
    )
    target_link_libraries(softbus_modbus_rtu_framer_test PRIVATE
        Qt6::Core
        Qt6::Test
    )

    qt_add_executable(softbus_protocol_parse_filter_test
        tests/protocol_parse_filter_test.cpp
        src/core/metadata/MetadataRegistry.cpp
        src/core/metadata/ProfileRegistry.cpp
        src/message_bus/pipeline/stages/3_filters/ProtocolParseFilter.cpp
    )

    qt_add_executable(softbus_modbus_rtu_pdu_codec_test
        tests/modbus_rtu_pdu_codec_test.cpp
        src/message_bus/pipeline/protocol/modbusrtu/ModbusRtuCodec.cpp
        src/message_bus/pipeline/stages/1_framers/ModbusRtuFraming.cpp
    )
    target_include_directories(softbus_modbus_rtu_pdu_codec_test PRIVATE
        ${CMAKE_SOURCE_DIR}
        ${CMAKE_SOURCE_DIR}/src
    )
    target_link_libraries(softbus_modbus_rtu_pdu_codec_test PRIVATE
        Qt6::Core
        Qt6::Test
    )
    target_include_directories(softbus_protocol_parse_filter_test PRIVATE
        ${CMAKE_SOURCE_DIR}
        ${CMAKE_SOURCE_DIR}/src
    )
    target_link_libraries(softbus_protocol_parse_filter_test PRIVATE
        Qt6::Core
        Qt6::Test
    )
endif()

install(TARGETS softbus_daemon
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
