cmake_minimum_required(VERSION 3.18)
project(pCoreCMake LANGUAGES C)

# -------------------------------
# Python
# -------------------------------
find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module)
include(PDynamoPython)
include(PDynamoTests)
include(PDynamoCython)
include(PDynamoExtensions)
include(PDynamoLibraries)
include(PDynamoInstall)

pd_configure_cython_option()
option(PDYNAMO_ENABLE_PCORE_FUNCTIONAL_TESTS "Enable legacy pCore functional tests." OFF)

# -------------------------------
# Paths
# -------------------------------
set(PCORE_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
set(EXT_DIR    ${PCORE_ROOT}/extensions)

set(LIBFILE    ${EXT_DIR}/libraries)
set(CINC_DIR   ${EXT_DIR}/cinclude)
set(CSRC_DIR   ${EXT_DIR}/csource)
set(PSRC_DIR   ${EXT_DIR}/psource)
set(PYREX_DIR  ${EXT_DIR}/pyrex)

set(PY_OUTPUT_DIR ${CMAKE_BINARY_DIR}/python/pCore)
set(GENERATED_DIR ${CMAKE_BINARY_DIR}/generated)

file(MAKE_DIRECTORY ${PY_OUTPUT_DIR})
file(MAKE_DIRECTORY ${GENERATED_DIR})

set(PCORE_SHIM_MODULES
    Clone
    CoreObjects
    LogFileWriter
    Serialization
)
set(PCORE_SHIM_FILES "")

foreach(MOD IN LISTS PCORE_SHIM_MODULES)
    set(SHIM_PATH "${CMAKE_BINARY_DIR}/python/${MOD}.py")
    file(WRITE "${SHIM_PATH}"
"from pCore.${MOD} import *\n")
    list(APPEND PCORE_SHIM_FILES "${SHIM_PATH}")
endforeach()

# -------------------------------
# Copy Python support files automatically
# - copy pCore/*.py
# - exclude original __init__.py
# - allow future exclusions
# -------------------------------
set(PCORE_PY_EXCLUDE
    #__init__.py
    # Add incompatible legacy files here if needed, e.g.
    # SomeLegacyFile.py
)

pd_copy_python_package(
    "${CMAKE_CURRENT_SOURCE_DIR}/pCore"
    "pCore"
    "${CMAKE_BINARY_DIR}/python"
    "${PCORE_PY_EXCLUDE}"
    PCORE_COPIED_PY_FILES
)

# -------------------------------
# Build low-level C libraries from libraries file
# -------------------------------
pd_load_c_libraries("${LIBFILE}" "${EXT_DIR}" "" PCORE_LIBS)

# Optional module exclusion list
set(PCORE_MODULE_EXCLUDE
    MatrixN3
    # Add broken or unsupported modules here if needed, e.g.
    # RandomNumberGenerator
)

pd_build_python_extensions(
    "pCore"
    "${PYREX_DIR}"
    "${PSRC_DIR}"
    "${CINC_DIR}"
    "${GENERATED_DIR}"
    "${PY_OUTPUT_DIR}"
    "${PCORE_MODULE_EXCLUDE}"
    ""
    ""
    "${PCORE_LIBS}"
    "pCore"
    PCORE_EXTENSION_TARGETS
    PCORE_MODULES
)

# -------------------------------
# Summary
# -------------------------------
message(STATUS "QBX_USE_CYTHON       : ${QBX_USE_CYTHON}")
message(STATUS "pCore libraries      : ${PCORE_LIBS}")
message(STATUS "Copied Python files  : ${PCORE_COPIED_PY_FILES}")
message(STATUS "Detected modules     : ${PCORE_MODULES}")
message(STATUS "Extension targets    : ${PCORE_EXTENSION_TARGETS}")
message(STATUS "Python output dir    : ${PY_OUTPUT_DIR}")
message(STATUS "Stable modules: ${PCORE_MODULES}")

set(PCORE_LIBS "${PCORE_LIBS}" PARENT_SCOPE)

# -------------------------------
# Test
# -------------------------------
pd_add_import_tests(
    "${CMAKE_CURRENT_SOURCE_DIR}/tests"
    "${CMAKE_BINARY_DIR}/python"
    "${CMAKE_BINARY_DIR}/python/pCore"
    "test_import_pcore"
    "test_import_all_extensions"
)

if(PDYNAMO_ENABLE_PCORE_FUNCTIONAL_TESTS)
    add_test(
        NAME test_morethuente_line_searching
        COMMAND ${Python3_EXECUTABLE}
                "${CMAKE_CURRENT_SOURCE_DIR}/tests/MoreThuenteLineSearching.py"
                "${CMAKE_BINARY_DIR}/python"
    )

    set_tests_properties(
        test_morethuente_line_searching
        PROPERTIES
        ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/python;PDYNAMO_PARAMETERS=${CMAKE_BINARY_DIR}/parameters;PDYNAMO_TEST_QUIET=1;PYTHONDONTWRITEBYTECODE=1"
    )
endif()

pd_install_python_package(
    "${CMAKE_CURRENT_SOURCE_DIR}/pCore"
    "pCore"
)

pd_install_extension_targets(
    "pCore"
    ${PCORE_EXTENSION_TARGETS}
)

pd_install_root_python_files(
    ${PCORE_SHIM_FILES}
)
