cmake_minimum_required(VERSION 3.20)
project(cf_pipeline_engine LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)

find_package(Python3 REQUIRED COMPONENTS Interpreter)

execute_process(
  COMMAND ${Python3_EXECUTABLE} -c "from pathlib import Path; import cf_ontology.datatypes_mapping as m; print(Path(m.__file__).resolve().with_name('type_registry.v0.json'))"
  OUTPUT_VARIABLE TYPE_REGISTRY_V0_SOURCE_PATH
  OUTPUT_STRIP_TRAILING_WHITESPACE
)

include(FetchContent)
FetchContent_Declare(
  nlohmann_json
  GIT_REPOSITORY https://github.com/nlohmann/json.git
  GIT_TAG v3.11.2
)
FetchContent_MakeAvailable(nlohmann_json)

add_library(cf_pipeline_v2_utils STATIC
  src/common/sha256.cpp
  src/common/type_registry.cc
  src/compiler/jsonld_loader.cpp
  src/compiler/signature.cpp
)

target_include_directories(cf_pipeline_v2_utils PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)

set(TYPE_REGISTRY_V0_FILENAME "type_registry.v0.json")

if (TYPE_REGISTRY_V0_SOURCE_PATH STREQUAL "" OR NOT EXISTS "${TYPE_REGISTRY_V0_SOURCE_PATH}")
  message(FATAL_ERROR "cf_ontology type_registry.v0.json not found in '${TYPE_REGISTRY_V0_SOURCE_PATH}'. Reinstall cf-ontology.")
endif()

file(TO_CMAKE_PATH "${TYPE_REGISTRY_V0_SOURCE_PATH}" TYPE_REGISTRY_V0_SOURCE_PATH)

target_compile_definitions(cf_pipeline_v2_utils PRIVATE
  CF_TYPE_REGISTRY_V0_PATH="${TYPE_REGISTRY_V0_SOURCE_PATH}"
  CF_TYPE_REGISTRY_V0_FILENAME="${TYPE_REGISTRY_V0_FILENAME}"
)

target_link_libraries(cf_pipeline_v2_utils PUBLIC nlohmann_json::nlohmann_json)

add_executable(cf_siggen tools/cf_siggen_main.cpp)
target_include_directories(cf_siggen PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_link_libraries(cf_siggen PRIVATE cf_pipeline_v2_utils)

set(GENERATED_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
file(MAKE_DIRECTORY ${GENERATED_DIR})

add_custom_command(
  OUTPUT ${GENERATED_DIR}/cf_test_signature_hashes.h
  COMMAND ${Python3_EXECUTABLE} -m cogniflow_pipeline_sdk.siggen
          --steps ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_steps.jsonld
          --out ${GENERATED_DIR}/cf_test_signature_hashes.h
          --scratch
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_steps.jsonld
  COMMENT "Generating test signature hashes"
)

add_library(cf_pipeline_v2_core STATIC
  src/compiler/pipeline_parser.cpp
  src/compiler/plan_builder.cpp
  src/plugin_loader/plugin_loader.cpp
  src/runtime/concurrency_controller.cpp
  src/scheduler/thread_pool.cpp
  src/scheduler/scheduler.cpp
)

target_include_directories(cf_pipeline_v2_core PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)

target_link_libraries(cf_pipeline_v2_core PUBLIC cf_pipeline_v2_utils)

if(UNIX AND NOT APPLE)
  target_link_libraries(cf_pipeline_v2_core PUBLIC dl)
endif()

add_executable(cf_pipeline_v2 src/main.cpp)

target_link_libraries(cf_pipeline_v2 PRIVATE cf_pipeline_v2_core)

add_custom_command(TARGET cf_pipeline_v2 POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
          ${TYPE_REGISTRY_V0_SOURCE_PATH}
          $<TARGET_FILE_DIR:cf_pipeline_v2>/${TYPE_REGISTRY_V0_FILENAME}
)

# Tests
add_library(cf_pipeline_v2_test_plugin SHARED
  ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_plugin.cpp
  ${GENERATED_DIR}/cf_test_signature_hashes.h
)

target_include_directories(cf_pipeline_v2_test_plugin PUBLIC
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
  ${GENERATED_DIR}
)

target_link_libraries(cf_pipeline_v2_test_plugin PUBLIC cf_pipeline_v2_utils)
target_compile_definitions(cf_pipeline_v2_test_plugin PRIVATE CF_STEP_ABI_EXPORTS)

set_target_properties(cf_pipeline_v2_test_plugin PROPERTIES
  RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests
  LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests
  ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests
)

add_executable(cf_pipeline_v2_tests tests/test_main.cpp)

target_include_directories(cf_pipeline_v2_tests PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR}/include
  ${CMAKE_CURRENT_SOURCE_DIR}/src
)

target_link_libraries(cf_pipeline_v2_tests PRIVATE cf_pipeline_v2_core)

add_custom_command(TARGET cf_pipeline_v2_tests POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
          ${TYPE_REGISTRY_V0_SOURCE_PATH}
          $<TARGET_FILE_DIR:cf_pipeline_v2_tests>/${TYPE_REGISTRY_V0_FILENAME}
)

install(TARGETS cf_siggen RUNTIME DESTINATION bin)
install(TARGETS cf_pipeline_v2 RUNTIME DESTINATION bin)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION include)
install(FILES ${TYPE_REGISTRY_V0_SOURCE_PATH} DESTINATION bin)
