# fastmm_strategies: the built-in strategies for every runtime (Sim, Replay, Live), exposed as the
# strategy module fastmm::register_builtin_strategies (include/fastmm/strategies/builtin.hpp), and
# the --list-strategies formatter the command-line entry points share. Needs fastmm::sim only: the
# Live factories use core's TscClock, LiveTransport and RingFeed, not the networking libraries.

# Internal, not installed: generates one source per (strategy, transport) holding one explicit
# factory instantiation, so the engines compile in parallel, and a registration file that only
# declares the factories. A strategy whose instantiation is missing fails to link.
#   fastmm_generate_strategy_module(<target> FUNCTION <ns::function> HEADER <declaring header>
#                                   STRATEGIES <Type> <header> [<Type> <header> ...])
function(fastmm_generate_strategy_module target)
  cmake_parse_arguments(A "" "FUNCTION;HEADER" "STRATEGIES" ${ARGN})
  set(dir ${CMAKE_CURRENT_BINARY_DIR}/generated/${target})
  set(transports sim replay live)
  set(includes "")
  set(calls "")
  list(LENGTH A_STRATEGIES n)
  math(EXPR last "${n} - 1")
  foreach(i RANGE 0 ${last} 2)
    math(EXPR j "${i} + 1")
    list(GET A_STRATEGIES ${i} type)
    list(GET A_STRATEGIES ${j} header)
    string(REGEX REPLACE "^.*::" "" stem "${type}")
    foreach(kind ${transports})
      file(CONFIGURE OUTPUT ${dir}/${stem}_${kind}.cpp @ONLY CONTENT
"// Generated by src/strategies/CMakeLists.txt; do not edit.
#include \"fastmm/strategies/factory_@kind@.hpp\"
#include \"@header@\"

FASTMM_INSTANTIATE_STRATEGY(@type@, @kind@);
")
      target_sources(${target} PRIVATE ${dir}/${stem}_${kind}.cpp)
    endforeach()
    string(APPEND includes "#include \"${header}\"\n")
    string(APPEND calls "  ::fastmm::register_strategy<${type}>(r);\n")
  endforeach()
  file(CONFIGURE OUTPUT ${dir}/register.cpp @ONLY CONTENT
"// Generated by src/strategies/CMakeLists.txt; do not edit. Declarations only: the factories are
// instantiated in the per-transport files next to this one.
#include \"@A_HEADER@\"
#include \"fastmm/strategies/module.hpp\"
@includes@
void @A_FUNCTION@(::fastmm::StrategyRegistry& r) {
@calls@}
")
  target_sources(${target} PRIVATE ${dir}/register.cpp)
endfunction()

file(GLOB FASTMM_STRATEGIES_SOURCES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
add_library(fastmm_strategies STATIC ${FASTMM_STRATEGIES_SOURCES})
add_library(fastmm::strategies ALIAS fastmm_strategies)
set_target_properties(fastmm_strategies PROPERTIES EXPORT_NAME strategies)
fastmm_target_defaults(fastmm_strategies)
target_link_libraries(fastmm_strategies PUBLIC fastmm::sim)
fastmm_generate_strategy_module(fastmm_strategies
  FUNCTION fastmm::register_builtin_strategies
  HEADER fastmm/strategies/builtin.hpp
  STRATEGIES
    fastmm::BasicMM           fastmm/strategies/basic_mm.hpp
    fastmm::AvellanedaStoikov fastmm/strategies/avellaneda_stoikov.hpp
    fastmm::OptionsMM         fastmm/strategies/options_mm.hpp
    fastmm::LeadMM            fastmm/strategies/lead_mm.hpp
    fastmm::Xmm               fastmm/strategies/xmm.hpp)
