cmake_minimum_required(VERSION 3.21)

# Only allow Linux builds
if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
    message(FATAL_ERROR "-- [ERROR] UNSUPPORTED SYSTEM: '${CMAKE_HOST_SYSTEM_NAME}'. SimpleBluez can only be built on Linux.")
endif()

include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/prelude.cmake)

project(
    simplebluez
    VERSION ${SIMPLEBLE_VERSION_BASE}
    DESCRIPTION "A simple C++ wrapper around Bluez with a commercially-friendly licence."
    HOMEPAGE_URL "https://github.com/OpenBluetoothToolbox/SimpleBluez"
    LANGUAGES CXX
)

# Run prelude script to set up environment
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/epilogue.cmake)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)

option(SIMPLEBLUEZ_INSTALL "Install SimpleBluez targets and package files" ON)

find_package(DBus1 REQUIRED)

if(NOT DEFINED SIMPLEDBUS_SANITIZE AND DEFINED SIMPLEBLUEZ_SANITIZE)
    set(SIMPLEDBUS_SANITIZE ${SIMPLEBLUEZ_SANITIZE})
endif()

# Load all variables that would eventually need to be exposed to downstream projects
if(NOT SIMPLEDBUS_LOG_LEVEL)
    set(SIMPLEDBUS_LOG_LEVEL "FATAL")
endif()

if(NOT SIMPLEBLUEZ_LOG_LEVEL)
    set(SIMPLEBLUEZ_LOG_LEVEL "FATAL")
endif()

set(SIMPLEBLUEZ_INCLUDE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/include
    ${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/external)

set(SIMPLEBLUEZ_SRC
    ${CMAKE_CURRENT_SOURCE_DIR}/src/Bluez.cpp    
    ${CMAKE_CURRENT_SOURCE_DIR}/src/Exceptions.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/Config.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/Logging.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Agent.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Advertisement.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/ServiceManager.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/CustomRoot.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Device.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Characteristic.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Service.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Adapter.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/BluezRoot.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/BluezOrg.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/BluezOrgBluez.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/standard/Descriptor.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Adapter1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Agent1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattDescriptor1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattCharacteristic1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattService1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Device1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Battery1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/AgentManager1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattManager1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/LEAdvertisement1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/LEAdvertisingManager1.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/Interface.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/Proxy.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Connection.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Exceptions.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Holder.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Logging.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Message.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Path.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/UnixSocket.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/interfaces/Introspectable.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/interfaces/ObjectManager.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/interfaces/Properties.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/Config.cpp
)

# Configure the build targets

add_library(simplebluez ${SIMPLEBLUEZ_SRC})
add_library(simplebluez::simplebluez ALIAS simplebluez)

set_target_properties(
    simplebluez PROPERTIES
    CXX_VISIBILITY_PRESET hidden
    VISIBILITY_INLINES_HIDDEN YES
    CXX_STANDARD 17
    POSITION_INDEPENDENT_CODE ON
    VERSION "${PROJECT_VERSION}"
    SOVERSION "${PROJECT_VERSION_MAJOR}"
    EXPORT_NAME simplebluez
    OUTPUT_NAME simplebluez
)

list(APPEND PRIVATE_COMPILE_DEFINITIONS SIMPLEDBUS_LOG_LEVEL=${SIMPLEDBUS_LOG_LEVEL})
list(APPEND PRIVATE_COMPILE_DEFINITIONS SIMPLEBLUEZ_LOG_LEVEL=${SIMPLEBLUEZ_LOG_LEVEL})

list(APPEND PRIVATE_COMPILE_DEFINITIONS FMT_HEADER_ONLY)

target_link_libraries(simplebluez PUBLIC ${DBus1_LIBRARIES})

target_include_directories(simplebluez PRIVATE ${SIMPLEBLUEZ_INCLUDE})
target_include_directories(simplebluez PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/external)
target_include_directories(simplebluez PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/internal/include)
target_include_directories(simplebluez INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/external>
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/include>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/simplebluez>)

append_sanitize_options("${SIMPLEBLUEZ_SANITIZE}")

apply_build_options(simplebluez
    "${PRIVATE_COMPILE_DEFINITIONS}"
    "${PRIVATE_COMPILE_OPTIONS}"
    "${PRIVATE_LINK_OPTIONS}"
    "${PUBLIC_LINK_OPTIONS}")

if(SIMPLEBLUEZ_INSTALL)
    set(SIMPLEBLUEZ_CMAKE_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/simplebluez)

    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/simplebluez.pc.in
                ${CMAKE_CURRENT_BINARY_DIR}/simplebluez.pc @ONLY)

    configure_package_config_file(
        ${CMAKE_CURRENT_SOURCE_DIR}/cmake/simplebluez-config.cmake.in
        ${CMAKE_CURRENT_BINARY_DIR}/simplebluez-config.cmake
        INSTALL_DESTINATION ${SIMPLEBLUEZ_CMAKE_INSTALL_DIR})

    write_basic_package_version_file(
        ${CMAKE_CURRENT_BINARY_DIR}/simplebluez-config-version.cmake
        VERSION ${PROJECT_VERSION}
        COMPATIBILITY SameMajorVersion)

    install(
        TARGETS simplebluez
        EXPORT simplebluez-targets
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

    install(
        EXPORT simplebluez-targets
        FILE simplebluez-targets.cmake
        NAMESPACE simplebluez::
        DESTINATION ${SIMPLEBLUEZ_CMAKE_INSTALL_DIR})

    install(
        FILES
            ${CMAKE_CURRENT_BINARY_DIR}/simplebluez-config.cmake
            ${CMAKE_CURRENT_BINARY_DIR}/simplebluez-config-version.cmake
        DESTINATION ${SIMPLEBLUEZ_CMAKE_INSTALL_DIR})

    install(
        DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/simplebluez/
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/simplebluez)

    install(
        DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../dependencies/external/
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/simplebluez)

    install(
        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/include/simpledbus/
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/simpledbus)

    install(
        FILES ${CMAKE_CURRENT_BINARY_DIR}/simplebluez.pc
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif()

if(SIMPLEBLUEZ_TEST)
    find_package(Python3 COMPONENTS Development REQUIRED)
    find_package(GTest REQUIRED)

    add_executable(simplebluez_test
        ${CMAKE_CURRENT_SOURCE_DIR}/test/src/main.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/test/src/helpers/PythonRunner.cpp)

    target_compile_definitions(simplebluez_test PRIVATE FMT_HEADER_ONLY)
    target_include_directories(simplebluez_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/external)
    target_include_directories(simplebluez_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/internal/include)

    set_target_properties(simplebluez_test PROPERTIES
        CXX_VISIBILITY_PRESET hidden
        VISIBILITY_INLINES_HIDDEN YES
        CXX_STANDARD 17
        POSITION_INDEPENDENT_CODE ON
        WINDOWS_EXPORT_ALL_SYMBOLS ON)

    target_link_libraries(simplebluez_test PRIVATE simplebluez::simplebluez ${GTEST_LIBRARIES} ${Python3_LIBRARIES} pthread)
    target_include_directories(simplebluez_test PRIVATE ${GTEST_INCLUDE_DIRS} ${Python3_INCLUDE_DIRS})

    add_custom_command (TARGET simplebluez_test POST_BUILD
        COMMAND "${CMAKE_COMMAND}" -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/test/python/ ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
    )
endif()
