# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
# 
#   http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

find_package(ZLIB REQUIRED)
find_package(UUID REQUIRED)
find_package(CURL REQUIRED)

set(SOURCES
        src/attribute.c src/bundle.c src/bundle_archive.c src/bundle_cache.c
        src/bundle_context.c src/bundle_revision.c src/capability.c src/celix_errorcodes.c
        src/framework.c src/manifest.c src/ioapi.c
        src/manifest_parser.c src/miniunz.c src/module.c
        src/requirement.c src/resolver.c src/service_reference.c src/service_registration.c
        src/service_registry.c src/service_tracker.c src/service_tracker_customizer.c
        src/unzip.c src/wire.c
        src/celix_log.c src/celix_launcher.c
        src/celix_framework_factory.c
        src/dm_dependency_manager_impl.c src/dm_component_impl.c
        src/dm_service_dependency.c src/dm_event.c src/celix_library_loader.c
)
add_library(framework SHARED ${SOURCES})
set_target_properties(framework PROPERTIES OUTPUT_NAME "celix_framework")
target_include_directories(framework PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
        $<INSTALL_INTERFACE:include/celix>
)
target_compile_options(framework PRIVATE -DUSE_FILE32API)
set_target_properties(framework PROPERTIES "SOVERSION" 2)

target_link_libraries(framework PUBLIC Celix::utils ${CELIX_OPTIONAL_EXTRA_LIBS})
target_link_libraries(framework PUBLIC UUID::lib CURL::libcurl ZLIB::ZLIB)

install(TARGETS framework EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework)
install(DIRECTORY include/ DESTINATION include/celix COMPONENT framework)

#Alias setup to match external usage
add_library(Celix::framework ALIAS framework)


if (ENABLE_TESTING)
    find_package(CppUTest REQUIRED)
    include_directories(${CPPUTEST_INCLUDE_DIR})
    add_subdirectory(tst)
endif()


celix_subproject(FRAMEWORK_TESTS "Option to build the framework tests" "OFF" DEPS)
if (ENABLE_TESTING AND FRAMEWORK_TESTS)
    find_package(CppUTest REQUIRED)

    include_directories(${CPPUTEST_INCLUDE_DIR})
    include_directories(${CPPUTEST_EXT_INCLUDE_DIR})
    include_directories(include src)


    add_executable(attribute_test
        private/test/attribute_test.cpp
        src/attribute.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(attribute_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

#    add_executable(bundle_archive_test
#        private/mock/celix_log_mock.c
#        private/test/bundle_archive_test.cpp #TODO: fix? contains invalid casts
#        src/bundle_revision.c
#        src/manifest.c
#        src/miniunz.c
#        src/unzip.c
#        src/ioapi.c
#        # src/properties.c
#        src/bundle_archive.c
#        src/celix_errorcodes.c
#        # src/utils.c
#        )
#    target_link_libraries(bundle_archive_test Celix::utils ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} ${ZLIB_LIBRARY} pthread)

    add_executable(bundle_cache_test
        private/test/bundle_cache_test.cpp
        private/mock/bundle_archive_mock.c
        private/mock/properties_mock.c
        src/bundle_cache.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(bundle_cache_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(bundle_context_test
        private/test/bundle_context_test.cpp
        private/mock/bundle_mock.c
        private/mock/framework_mock.c
        private/mock/service_registry_mock.c
        private/mock/service_registration_mock.c
        private/mock/service_reference_mock.c
        src/service_tracker.c #TODO make mock for svc tracker
        src/service_tracker_customizer.c
        src/bundle_context.c
        private/mock/module_mock.c
        src/celix_errorcodes.c
        private/mock/dm_dependency_manager_mock.c
        private/mock/celix_log_mock.c)
    target_link_libraries(bundle_context_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(bundle_revision_test
        private/test/bundle_revision_test.cpp
        private/mock/miniunz_mock.c
        private/mock/manifest_mock.c
        src/bundle_revision.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(bundle_revision_test ZLIB::ZLIB ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(bundle_test
        private/test/bundle_test.cpp
        private/mock/framework_mock.c
        private/mock/module_mock.c
        private/mock/bundle_archive_mock.c
        private/mock/bundle_revision_mock.c
        private/mock/resolver_mock.c
        private/mock/version_mock.c
        src/bundle.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(bundle_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(capability_test
        private/test/capability_test.cpp
        private/mock/attribute_mock.c
        private/mock/version_mock.c
        src/capability.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(capability_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(celix_errorcodes_test
        private/test/celix_errorcodes_test.cpp
        src/celix_errorcodes.c)
    target_link_libraries(celix_errorcodes_test ${CPPUTEST_LIBRARY} Celix::utils)

    add_executable(framework_test
        private/test/framework_test.cpp
        #private/mock/properties_mock.c
        private/mock/resolver_mock.c
        private/mock/service_reference_mock.c
        private/mock/service_registry_mock.c
        private/mock/service_registration_mock.c
        private/mock/filter_mock.c
        private/mock/bundle_mock.c
        private/mock/bundle_context_mock.c
        private/mock/module_mock.c
        private/mock/bundle_archive_mock.c
        private/mock/bundle_revision_mock.c
        private/mock/bundle_cache_mock.c
        private/mock/manifest_mock.c
        private/mock/dm_dependency_manager_mock.c
        private/mock/service_tracker_stub.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c
        src/framework.c
        src/celix_library_loader.c)
    target_link_libraries(framework_test PRIVATE ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} UUID::lib Celix::utils pthread dl)

    add_executable(manifest_parser_test
        private/test/manifest_parser_test.cpp
        private/mock/manifest_mock.c
        private/mock/version_mock.c
        private/mock/version_range_mock.c
        src/attribute.c
        src/capability.c
        src/requirement.c
        src/manifest_parser.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(manifest_parser_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(manifest_test
        private/test/manifest_test.cpp
        private/mock/properties_mock.c
        src/manifest.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(manifest_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

#    add_executable(module_test
#        private/test/module_test.cpp # TODO: fix invalid conversions from char ** to const char**
#        private/mock/bundle_mock.c
#        private/mock/version_mock.c
#        private/mock/manifest_mock.c
#        private/mock/manifest_parser_mock.c
#        private/mock/capability_mock.c
#        private/mock/requirement_mock.c
#        private/mock/wire_mock.c
#        src/module.c)
#    target_link_libraries(module_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
#    target_include_directories(module_test SYSTEM ${CPPUTEST_INCLUDE_DIR})

    add_executable(requirement_test
        private/test/requirement_test.cpp
        private/mock/attribute_mock.c
        private/mock/capability_mock.c
        private/mock/version_range_mock.c
        src/requirement.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(requirement_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

#    add_executable(resolver_test
#        private/test/resolver_test.cpp #TODO: fix missing include
#        private/mock/bundle_mock.c
#        private/mock/requirement_mock.c
#        private/mock/capability_mock.c
#        private/mock/manifest_parser_mock.c
#        private/mock/version_mock.c
#        src/wire.c
#        src/module.c
#        src/resolver.c
#        src/celix_errorcodes.c
#        private/mock/celix_log_mock.c)
#    target_link_libraries(resolver_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(service_reference_test
        private/test/service_reference_test.cpp
        private/mock/properties_mock.c
        private/mock/service_registration_mock.c
        private/mock/service_registry_mock.c
        src/service_reference.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(service_reference_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

     add_executable(service_registration_test
        private/test/service_registration_test.cpp
        private/mock/service_registry_mock.c
        src/service_registration.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(service_registration_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(service_registry_test
        private/test/service_registry_test.cpp
        private/mock/framework_mock.c
        private/mock/bundle_mock.c
        private/mock/filter_mock.c
        private/mock/service_reference_mock.c
        private/mock/service_registration_mock.c
        private/mock/properties_mock.c
        src/service_registry.c
        private/mock/module_mock.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(service_registry_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(service_tracker_customizer_test
        private/test/service_tracker_customizer_test.cpp
        private/mock/service_reference_mock.c
        src/service_tracker_customizer.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c)
    target_link_libraries(service_tracker_customizer_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

#        add_executable(service_tracker_test 
#            private/test/service_tracker_test.cpp 
#            private/mock/bundle_context_mock.c
#            private/mock/service_reference_mock.c 
#            private/mock/service_tracker_customizer_mock.c
#            src/service_tracker.c
#            src/celix_errorcodes.c
#            private/mock/celix_log_mock.c)
#        target_link_libraries(service_tracker_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)

    add_executable(wire_test
        private/mock/requirement_mock.c
        private/mock/capability_mock.c
        private/mock/module_mock.c
        src/celix_errorcodes.c
        private/mock/celix_log_mock.c
        src/wire.c
        private/test/wire_test.cpp)
    target_link_libraries(wire_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils)

    configure_file(private/resources-test/manifest_sections.txt ${CMAKE_CURRENT_BINARY_DIR}/resources-test/manifest_sections.txt COPYONLY)
    configure_file(private/resources-test/manifest.txt ${CMAKE_CURRENT_BINARY_DIR}/resources-test/manifest.txt COPYONLY)

#    set_target_properties(wire_test PROPERTIES COMPILE_FLAGS "-include ${CPPUTEST_INCLUDE_DIR}/CppUTest/MemoryLeakDetectorMallocMacros.h -include ${CPPUTEST_INCLUDE_DIR}/CppUTest/MemoryLeakDetectorNewMacros.h")

    add_test(NAME attribute_test COMMAND attribute_test)
#    add_test(NAME bundle_archive_test COMMAND bundle_archive_test)
    add_test(NAME bundle_cache_test COMMAND bundle_cache_test)
    add_test(NAME bundle_context_test COMMAND bundle_context_test)
    add_test(NAME bundle_revision_test  COMMAND bundle_revision_test)
    add_test(NAME bundle_test COMMAND bundle_test)
    add_test(NAME capability_test COMMAND capability_test)
    add_test(NAME celix_errorcodes_test COMMAND celix_errorcodes_test)
    add_test(NAME framework_test COMMAND framework_test)
    add_test(NAME manifest_parser_test COMMAND manifest_parser_test)
    add_test(NAME manifest_test COMMAND manifest_test)
#    add_test(NAME module_test COMMAND module_test)
    add_test(NAME requirement_test COMMAND requirement_test)
#    add_test(NAME resolver_test COMMAND resolver_test)
    add_test(NAME service_reference_test COMMAND service_reference_test)
    add_test(NAME service_registration_test COMMAND service_registration_test)
    add_test(NAME service_registry_test COMMAND service_registry_test)
    add_test(NAME service_tracker_customizer_test COMMAND service_tracker_customizer_test)
#    add_test(NAME service_tracker_test COMMAND service_tracker_test)
    add_test(NAME wire_test COMMAND wire_test)

    SETUP_TARGET_FOR_COVERAGE(attribute_test attribute_test ${CMAKE_BINARY_DIR}/coverage/attribute_test/attribute_test)
#    SETUP_TARGET_FOR_COVERAGE(bundle_archive_test bundle_archive_test ${CMAKE_BINARY_DIR}/coverage/bundle_archive_test/bundle_archive_test)
    SETUP_TARGET_FOR_COVERAGE(bundle_cache_test bundle_cache_test ${CMAKE_BINARY_DIR}/coverage/bundle_cache_test/bundle_cache_test)
    SETUP_TARGET_FOR_COVERAGE(bundle_context_test bundle_context_test ${CMAKE_BINARY_DIR}/coverage/bundle_context_test/bundle_context_test)
    SETUP_TARGET_FOR_COVERAGE(bundle_revision_test bundle_revision_test ${CMAKE_BINARY_DIR}/coverage/bundle_revision_test/bundle_revision_test)
    SETUP_TARGET_FOR_COVERAGE(bundle_test bundle_test ${CMAKE_BINARY_DIR}/coverage/bundle_test/bundle_test)
    SETUP_TARGET_FOR_COVERAGE(capability_test capability_test ${CMAKE_BINARY_DIR}/coverage/capability_test/capability_test)
    SETUP_TARGET_FOR_COVERAGE(celix_errorcodes_test celix_errorcodes_test ${CMAKE_BINARY_DIR}/coverage/celix_errorcodes_test/celix_errorcodes_test)
    SETUP_TARGET_FOR_COVERAGE(framework_test framework_test ${CMAKE_BINARY_DIR}/coverage/framework_test/framework_test)
    SETUP_TARGET_FOR_COVERAGE(manifest_parser_test manifest_parser_test ${CMAKE_BINARY_DIR}/coverage/manifest_parser_test/manifest_parser_test)
    SETUP_TARGET_FOR_COVERAGE(manifest_test manifest_test ${CMAKE_BINARY_DIR}/coverage/manifest_test/manifest_test)
#    SETUP_TARGET_FOR_COVERAGE(module_test module_test ${CMAKE_BINARY_DIR}/coverage/module_test/module_test)
    SETUP_TARGET_FOR_COVERAGE(requirement_test requirement_test ${CMAKE_BINARY_DIR}/coverage/requirement_test/requirement_test)
#    SETUP_TARGET_FOR_COVERAGE(resolver_test resolver_test ${CMAKE_BINARY_DIR}/coverage/resolver_test/resolver_test)
    SETUP_TARGET_FOR_COVERAGE(service_reference_test service_reference_test ${CMAKE_BINARY_DIR}/coverage/service_reference_test/service_reference_test)
    SETUP_TARGET_FOR_COVERAGE(service_registration_test service_registration_test ${CMAKE_BINARY_DIR}/coverage/service_registration_test/service_registration_test)
    SETUP_TARGET_FOR_COVERAGE(service_registry_test service_registry_test ${CMAKE_BINARY_DIR}/coverage/service_registry_test/service_registry_test)
    SETUP_TARGET_FOR_COVERAGE(service_tracker_customizer_test service_tracker_customizer_test ${CMAKE_BINARY_DIR}/coverage/service_tracker_customizer_test/service_tracker_customizer_test)
#    SETUP_TARGET_FOR_COVERAGE(service_tracker_test service_tracker_test ${CMAKE_BINARY_DIR}/coverage/service_tracker_test/service_tracker_test)
    SETUP_TARGET_FOR_COVERAGE(wire_test wire_test ${CMAKE_BINARY_DIR}/coverage/wire_test/wire_test)

endif (ENABLE_TESTING AND FRAMEWORK_TESTS)
