cmake_minimum_required(VERSION 3.18)
project(cuda_mppi LANGUAGES CXX CUDA)

if(NOT CMAKE_CUDA_ARCHITECTURES)
    set(CMAKE_CUDA_ARCHITECTURES "75;86;89")
endif()

set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)

# Export compile commands for IDE integration
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Suppress Eigen/CUDA constexpr warnings
add_compile_options($<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>)

find_package(Eigen3 REQUIRED)
find_package(CUDAToolkit REQUIRED)
find_package(Python 3.12 COMPONENTS Interpreter Development.Module REQUIRED)
find_package(nanobind CONFIG REQUIRED)

# Gather sources
file(GLOB_RECURSE SOURCES "src/*.cu" "src/*.cpp")
file(GLOB_RECURSE HEADERS "include/*.cuh" "include/*.h" "include/*.hpp")

# JIT compiler sources (these need to be compiled separately)
set(JIT_SOURCES
    src/jit/jit_compiler.cpp
    src/jit/jit_mppi_controller.cpp
)

# Define header-only library (renamed to avoid conflict with extension)
add_library(cuda_mppi_lib INTERFACE)

# Interface dependencies
target_link_libraries(cuda_mppi_lib INTERFACE
    Eigen3::Eigen
    CUDA::curand
    CUDA::nvrtc
    CUDA::cuda_driver
)
# Interface include directories
target_include_directories(cuda_mppi_lib INTERFACE
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
    ${EIGEN3_INCLUDE_DIR}
)

# Python Extension (this will be jax_mppi.cuda_mppi)
nanobind_add_module(cuda_mppi bindings/bindings.cu ${JIT_SOURCES})
target_link_libraries(cuda_mppi PRIVATE cuda_mppi_lib)

# Install into the python package
install(TARGETS cuda_mppi DESTINATION .)
install(DIRECTORY include/mppi DESTINATION include)

# Example executable to verify build (disabled due to Eigen/CUDA compatibility warnings)
# add_executable(mppi_test src/main_test.cu)
# target_link_libraries(mppi_test PRIVATE cuda_mppi_lib)

add_executable(pendulum_test src/pendulum_test.cu)
target_link_libraries(pendulum_test PRIVATE cuda_mppi_lib)

add_executable(i_mppi_test src/i_mppi_test.cu)
target_link_libraries(i_mppi_test PRIVATE cuda_mppi_lib)

add_executable(i_mppi_sim src/i_mppi_sim.cu)
target_link_libraries(i_mppi_sim PRIVATE cuda_mppi_lib)

# FSMI unit tests
add_executable(fsmi_unit_test src/fsmi_unit_test.cu)
target_link_libraries(fsmi_unit_test PRIVATE cuda_mppi_lib)

# Full informative simulation (quadrotor + FSMI + info field)
add_executable(informative_sim src/informative_sim.cu)
target_link_libraries(informative_sim PRIVATE cuda_mppi_lib)
