if (CMAKE_HOST_WIN32)
    cmake_minimum_required(VERSION 3.21)
else()
    cmake_minimum_required(VERSION 3.16)
endif()
cmake_policy(SET CMP0079 NEW)

if(NOT DEFINED LIBINT_VERSION)
    # for indep bld of project(libint2-python), version (for pyproject.toml) not available from project(Libint2)
    list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules)
    include(int_computed OPTIONAL)  # cmake+cmake

    if(NOT DEFINED LIBINT_VERSION)
        set(LIBINT_VERSION "2.13.0")
    endif()
endif()

project(
  libint2-python
  VERSION ${LIBINT_VERSION}
  )

if (NOT TARGET Python::Module)
    find_package(Python COMPONENTS Interpreter Development REQUIRED)
endif()

find_package(pybind11 3.0.0 CONFIG)
if (NOT TARGET pybind11::module)
    message(STATUS "Suitable pybind11 could not be located, building pybind11 instead.")

    # [LAB May 2023] For a long time this was fixed at v2.4.3 from a Valeev group clone.
    #  * recently noticed that C++17 is not getting processed right for this version (at least with the Ubuntu GHA setup)
    #  * so bumping the backup tag to v2.6.0 (c.2021). the v2.4.3 could probably be revived if needed.
    include(FetchContent)
    FetchContent_Declare(
            pybind11
            GIT_REPOSITORY "https://github.com/pybind/pybind11.git"
            GIT_TAG "v3.0.1"
            GIT_SHALLOW
            EXCLUDE_FROM_ALL
            SYSTEM
    )

    FetchContent_MakeAvailable(pybind11)
    set(pybind11_VERSION "3.0.1")  # getting the fetched version isn't reliable from ${CMAKE_PROJECT_VERSION}), so sync explicitly from tag above
endif()

if (pybind11_VERSION VERSION_GREATER_EQUAL 2.11.0)
    # ipo/lto triggering changed https://github.com/pybind/pybind11/pull/4643
    if ((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
        # clang-cl

        # this variable needs to be defined, not the property
        set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)
    endif()
endif()

pybind11_add_module(
  libint2-python
  MODULE
    src/libint2/libint2.cc
    src/libint2/engine.cc
  )

target_compile_features(libint2-python PRIVATE "cxx_std_17")

if (pybind11_VERSION VERSION_GREATER_EQUAL 2.7.0)
    # suppress error in L2
    # * https://github.com/pybind/pybind11/pull/2919
    target_compile_definitions(libint2-python PRIVATE NDEBUG=1)
endif()

target_compile_options(libint2-python
  PRIVATE
    #$<$<BOOL:${MSVC}>:/W4>
    $<$<NOT:$<BOOL:${MSVC}>>:-Wall>
  )

#find_package(Eigen3 3.3 REQUIRED)

set_target_properties(
  libint2-python
  PROPERTIES
    #PREFIX ""
    OUTPUT_NAME libint2
  )

# future note: this whole block could likely be replaced by the below, but perhaps explicit better for now
# * `if(TARGET Libint2::cxx)\n  target_link_libraries(libint2-python PRIVATE Libint2::cxx)\nelse()\n  find_package(Libint2 ...`
if (TARGET Libint2::cxx)


    if (MSVC)
        target_compile_definitions(libint2-python PUBLIC _USE_MATH_DEFINES)
        target_compile_options(libint2-python PUBLIC "/EHsc")
    endif()

    target_link_libraries(
      libint2-python
      PRIVATE
        Libint2::cxx
        Boost::headers
      )
else()
    find_package(Libint2 REQUIRED)
    target_link_libraries(libint2-python PRIVATE Libint2::cxx)
endif()

# if (Eigen3::Eigen)
#   target_link_libraries(libint2-python INTERFACE Eigen3::Eigen)
# else()
#   include_directories(${EIGEN3_INCLUDE_DIR})
# endif()

configure_file(pyproject.toml ${PROJECT_BINARY_DIR}/pyproject.toml @ONLY)

# Install the Python module to the correct location for scikit-build-core
install(TARGETS libint2-python
  LIBRARY DESTINATION libint2
  RUNTIME DESTINATION libint2
)

#  <<<  Install  >>>

if (LIBINT2_PREFIX_PYTHON_INSTALL)
    # * Note that this block is *Linux-style* install to `CMAKE_INSTALL_PREFIX`.
    # * For *Python-style* install to `Python_EXECUTABLE`'s site-packages, use
    #   wheel target below from python/ directory.
    #     > make libint2-python-wheel
    #     > pip3 install dist/libint2-*.whl

    execute_process(
      COMMAND ${Python_EXECUTABLE} -c
        "import os, sys, sysconfig as s; spdir = s.get_path('platlib'); print(spdir.replace(os.path.commonpath([sys.prefix, spdir]), '').lstrip(os.path.sep));"
      OUTPUT_VARIABLE LIBINT2_INSTALL_PYMODDIR
      OUTPUT_STRIP_TRAILING_WHITESPACE
      )
    message(STATUS "Showing option LIBINT2_INSTALL_PYMODDIR: ${LIBINT2_INSTALL_PYMODDIR} (non-user-configurable until wanted)")

    install(
      FILES $<TARGET_FILE:libint2-python>
      COMPONENT ${L2}_Python
      DESTINATION ${LIBINT2_INSTALL_PYMODDIR}
      )
endif()

#  <<<  Python Tooling  >>>

add_custom_target(
  libint2-python-test
  DEPENDS libint2-python
  COMMAND ${Python_EXECUTABLE} -m pytest ${CMAKE_CURRENT_SOURCE_DIR}/tests -v
  WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
  )
add_custom_target(check-python DEPENDS libint2-python-test)

add_custom_target(
  libint2-python-wheel
  DEPENDS libint2-python
  COMMAND ${Python_EXECUTABLE} -m build --wheel ${PROJECT_BINARY_DIR}
  WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
  )

enable_testing()

# add the executable
add_test(
  NAME libint2-python
  COMMAND ${Python_EXECUTABLE} -m pytest ${CMAKE_CURRENT_SOURCE_DIR}/tests -v
  WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
  )
