cmake_minimum_required(VERSION 3.15)

project(${SKBUILD_PROJECT_NAME} LANGUAGES CXX)

# ----------------------------
# C++ standard
# ----------------------------
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# ----------------------------
# Ensure CMAKE_BUILD_TYPE and install config
# ----------------------------
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
endif()
set(CMAKE_INSTALL_CONFIG_NAME ${CMAKE_BUILD_TYPE})

message(STATUS "CMake build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "CMake install config name: ${CMAKE_INSTALL_CONFIG_NAME}")

# ----------------------------
# Dependencies
# ----------------------------
find_package(pybind11 REQUIRED)
find_package(OpenMP REQUIRED)
#find_package(OpenCV REQUIRED)
find_package(TIFF REQUIRED)
message(STATUS "TIFF_FOUND = ${TIFF_FOUND}")
message(STATUS "TIFF_INCLUDE_DIR = ${TIFF_INCLUDE_DIR}")
message(STATUS "TIFF_LIBRARIES = ${TIFF_LIBRARIES}")
# ----------------------------
# Eigen3
# ----------------------------
find_package(Eigen3 3.4 QUIET)

if (Eigen3_FOUND)
    message(STATUS "Using system-installed Eigen3")
    if (TARGET Eigen3::Eigen)
        get_target_property(EIGEN_INC Eigen3::Eigen INTERFACE_INCLUDE_DIRECTORIES)
        message(STATUS "Eigen3 include dir: ${EIGEN_INC}")
    endif()
    if (DEFINED Eigen3_DIR)
        message(STATUS "Eigen3 CMake config located at: ${Eigen3_DIR}")
    endif()
else()
    message(STATUS "System Eigen3 not found. fetching with FetchContent")
    include(FetchContent)

    FetchContent_Declare(
        eigen
        GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
        GIT_TAG 3.4.0
    )
    FetchContent_MakeAvailable(eigen)

    message(STATUS "Using Eigen3 from FetchContent")
    message(STATUS "Eigen3 source dir: ${eigen_SOURCE_DIR}")
    message(STATUS "Eigen3 binary dir: ${eigen_BINARY_DIR}")
endif()

# -----------------------------------------------------------------------------
# compile/link flags based on platform
# -----------------------------------------------------------------------------
function(apply_compile_flags target_name)
    if(MSVC)
        # Windows (MSVC)
        target_compile_options(${target_name} PRIVATE /openmp)
        if(CMAKE_BUILD_TYPE STREQUAL "Debug")
            message(STATUS "Applying MSVC debug flags for ${target_name}")
            target_compile_options(${target_name} PRIVATE /Od /Zi)
        else()
            message(STATUS "Applying MSVC release flags for ${target_name}")
            target_compile_options(${target_name} PRIVATE /O2)
        endif()
    else()
        # Linux / macOS
        target_compile_options(${target_name} PRIVATE -fopenmp)
        if(CMAKE_BUILD_TYPE STREQUAL "Debug")
            message(STATUS "Applying debug flags for ${target_name}")
            target_compile_options(${target_name} PRIVATE -O0 -g)
            target_link_options(${target_name} PRIVATE -fopenmp -g)
        else()
            message(STATUS "Applying release flags for ${target_name}")
            target_compile_options(${target_name} PRIVATE -O3)
            target_link_options(${target_name} PRIVATE -fopenmp)
        endif()
    endif()
endfunction()

# ----------------------------
# COMMON_CPP module
# ----------------------------
file(GLOB COMMON_SRC_FILES src/pyvale/commoncpp/*.cpp)

pybind11_add_module(commoncpp MODULE ${COMMON_SRC_FILES})
target_include_directories(commoncpp PRIVATE src/pyvale/commoncpp ${TIFF_INCLUDE_DIR})
target_link_libraries(commoncpp PRIVATE OpenMP::OpenMP_CXX Eigen3::Eigen ${TIFF_LIBRARIES})
apply_compile_flags(commoncpp)
install(TARGETS commoncpp LIBRARY DESTINATION pyvale/commoncpp)

# ----------------------------
# DIC module
# ----------------------------
file(GLOB DIC_SRC_FILES src/pyvale/dic/cpp/*.cpp)

pybind11_add_module(diccpp MODULE ${DIC_SRC_FILES} ${COMMON_SRC_FILES})
target_include_directories(diccpp PRIVATE src/pyvale/commoncpp src/pyvale/dic ${TIFF_INCLUDE_DIR})
target_link_libraries(diccpp PRIVATE OpenMP::OpenMP_CXX Eigen3::Eigen ${TIFF_LIBRARIES})
apply_compile_flags(diccpp)
install(TARGETS diccpp LIBRARY DESTINATION pyvale/dic)

# ----------------------------
# DIC Calibration
# ----------------------------
file(GLOB CALIB_SRC_FILES src/pyvale/calib/cpp/*.cpp)

pybind11_add_module(calibcpp MODULE ${CALIB_SRC_FILES} ${COMMON_SRC_FILES})
target_include_directories(calibcpp PRIVATE src/pyvale/commoncpp src/pyvale/calib ${TIFF_INCLUDE_DIR})
target_link_libraries(calibcpp PRIVATE OpenMP::OpenMP_CXX Eigen3::Eigen ${TIFF_LIBRARIES})
apply_compile_flags(calibcpp)
install(TARGETS calibcpp LIBRARY DESTINATION pyvale/calib)

# ----------------------------
# STRAIN module
# ----------------------------
file(GLOB STRAIN_SRC_FILES src/pyvale/strain/cpp/*.cpp)

pybind11_add_module(strain_cpp MODULE ${STRAIN_SRC_FILES} ${COMMON_SRC_FILES})
target_include_directories(strain_cpp PRIVATE src/pyvale/commoncpp src/pyvale/strain ${TIFF_INCLUDE_DIR})
target_link_libraries(strain_cpp PRIVATE OpenMP::OpenMP_CXX Eigen3::Eigen ${TIFF_LIBRARIES}) 
apply_compile_flags(strain_cpp)
install(TARGETS strain_cpp LIBRARY DESTINATION pyvale/strain)

