cmake_minimum_required(VERSION 3.15)
project(covalent_base LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Disable LTO/IPO to avoid link-time issues with mixed static/shared pybind targets
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)

# manylinux_2_28 currently provides Eigen 3.3.x; with GCC 14 this emits
# deprecation warnings from std::unary_negate/binary_negate in Eigen headers.
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14)
  add_compile_options(-Wno-deprecated-declarations)
endif()

# ---------------------------------------------------------------------------
# Dependency location configuration
# ---------------------------------------------------------------------------

set(ROBOT_DEPS_ROOT "" CACHE PATH
    "Root directory that contains manually built third-party libraries (libtorch, cnpy, iir1)")
if(DEFINED ENV{ROBOT_DEPS_ROOT} AND NOT ROBOT_DEPS_ROOT)
  set(ROBOT_DEPS_ROOT "$ENV{ROBOT_DEPS_ROOT}" CACHE PATH
      "Root directory that contains manually built third-party libraries (libtorch, cnpy, iir1)" FORCE)
endif()

if(NOT ROBOT_DEPS_ROOT)
  set(_robot_default_deps "$ENV{HOME}/opt/robot-deps")
  if(EXISTS "${_robot_default_deps}")
    set(ROBOT_DEPS_ROOT "${_robot_default_deps}")
  endif()
endif()

set(ROBOT_LIBTORCH_ROOT "" CACHE PATH
    "Path to the libtorch installation (directory that contains share/cmake/Torch)")
if(DEFINED ENV{ROBOT_LIBTORCH_ROOT} AND NOT ROBOT_LIBTORCH_ROOT)
  set(ROBOT_LIBTORCH_ROOT "$ENV{ROBOT_LIBTORCH_ROOT}" CACHE PATH
      "Path to the libtorch installation (directory that contains share/cmake/Torch)" FORCE)
endif()
if(NOT ROBOT_LIBTORCH_ROOT AND ROBOT_DEPS_ROOT)
  if(EXISTS "${ROBOT_DEPS_ROOT}/libtorch")
    set(ROBOT_LIBTORCH_ROOT "${ROBOT_DEPS_ROOT}/libtorch")
  endif()
endif()

macro(_stb_append_prefix)
  foreach(_dir IN LISTS ARGN)
    if(_dir AND EXISTS "${_dir}")
      list(APPEND CMAKE_PREFIX_PATH "${_dir}")
    endif()
  endforeach()
endmacro()

if(ROBOT_DEPS_ROOT)
  _stb_append_prefix(
    "${ROBOT_DEPS_ROOT}"
    "${ROBOT_DEPS_ROOT}/lib"
    "${ROBOT_DEPS_ROOT}/lib64"
    "${ROBOT_DEPS_ROOT}/lib/cmake"
    "${ROBOT_DEPS_ROOT}/share/cmake")
  message(STATUS "ROBOT_DEPS_ROOT: ${ROBOT_DEPS_ROOT}")
endif()

if(ROBOT_LIBTORCH_ROOT)
  _stb_append_prefix(
    "${ROBOT_LIBTORCH_ROOT}"
    "${ROBOT_LIBTORCH_ROOT}/lib"
    "${ROBOT_LIBTORCH_ROOT}/lib64"
    "${ROBOT_LIBTORCH_ROOT}/share/cmake"
    "${ROBOT_LIBTORCH_ROOT}/share/cmake/Torch")
  if(EXISTS "${ROBOT_LIBTORCH_ROOT}/share/cmake/Torch/TorchConfig.cmake")
    set(Torch_DIR "${ROBOT_LIBTORCH_ROOT}/share/cmake/Torch" CACHE PATH
        "Directory containing TorchConfig.cmake" FORCE)
  endif()
  message(STATUS "ROBOT_LIBTORCH_ROOT: ${ROBOT_LIBTORCH_ROOT}")
endif()

list(REMOVE_DUPLICATES CMAKE_PREFIX_PATH)
list(REMOVE_DUPLICATES CNPY_HINT_DIRS)
list(REMOVE_DUPLICATES IIR_HINT_DIRS)

set(PYBIND11_FINDPYTHON ON)
find_package(pybind11 QUIET)
if(NOT pybind11_FOUND)
  message(STATUS "pybind11 not found; Python modules will not be built")
endif()

# Try to locate Torch via the active Python environment (e.g., venv-installed torch)
if(NOT Python3_Interpreter_FOUND)
  find_package(Python3 COMPONENTS Interpreter QUIET)
endif()
if(NOT Torch_DIR AND Python3_Interpreter_FOUND)
  execute_process(
    COMMAND ${Python3_EXECUTABLE} -c "import importlib.util, pathlib; spec=importlib.util.find_spec('torch'); import sys; print((pathlib.Path(spec.origin).parent/'share/cmake/Torch').as_posix() if spec else '')"
    OUTPUT_VARIABLE _torch_cmake_from_python
    OUTPUT_STRIP_TRAILING_WHITESPACE
  )
  if(_torch_cmake_from_python AND EXISTS "${_torch_cmake_from_python}/TorchConfig.cmake")
    set(Torch_DIR "${_torch_cmake_from_python}" CACHE PATH
        "Directory containing TorchConfig.cmake (auto-detected from Python torch)" FORCE)
    list(APPEND CMAKE_PREFIX_PATH "${_torch_cmake_from_python}")
    message(STATUS "Torch CMake dir auto-detected from Python: ${_torch_cmake_from_python}")
  endif()
endif()
find_package(Eigen3 QUIET)

find_package(Torch QUIET)
if(NOT Torch_FOUND AND ROBOT_LIBTORCH_ROOT)
  find_package(Torch QUIET
               PATHS
                 "${ROBOT_LIBTORCH_ROOT}"
                 "${ROBOT_LIBTORCH_ROOT}/share/cmake/Torch"
               NO_DEFAULT_PATH)
endif()

if(Torch_FOUND)
  message(STATUS "Torch found; linking against: ${TORCH_LIBRARIES}")
endif()

add_subdirectory(control)
