cmake_minimum_required(VERSION 3.0.2)
project(robot_depth_image_proc VERSION 1.0.0 LANGUAGES CXX)

# ========================================================
# Detect build mode
# ========================================================
if(DEFINED CATKIN_DEVEL_PREFIX OR DEFINED CATKIN_TOPLEVEL)
  set(BUILDING_WITH_CATKIN TRUE)
  message(STATUS "Building robot_depth_image_proc with Catkin")
else()
  set(BUILDING_WITH_CATKIN FALSE)
  message(STATUS "Building robot_depth_image_proc with Standalone CMake")
endif()

# ========================================================
# C++ Standard
# ========================================================
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

add_compile_options(-Wall -Wextra -Wpedantic)

# ========================================================
# Common dependencies
# ========================================================
find_package(Boost REQUIRED COMPONENTS thread)
find_package(Eigen3 REQUIRED)

# ========================================================
# Standalone mode
# ========================================================
if(NOT BUILDING_WITH_CATKIN)

  set(CMAKE_POSITION_INDEPENDENT_CODE ON)

  set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
  set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
  set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}")

  # ⚠️ placeholder libraries
  set(PACKAGES_DIR
    cv_bridge
    robot_sensor_msgs
    robot_cpp
    data_convert
    robot_image_geometry
  )

  find_library(TF3_LIBRARY
    NAMES tf3
    PATHS /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu
  )

  if(NOT TF3_LIBRARY)
    message(FATAL_ERROR "❌ tf3 library not found")
  endif()

# ========================================================
# Catkin mode
# ========================================================
else()

  find_package(catkin REQUIRED COMPONENTS
    cv_bridge
    robot_sensor_msgs
    robot_cpp
    data_convert
    robot_image_geometry
    roscpp
    sensor_msgs
    std_msgs
    tf2_ros
  )

  find_library(TF3_LIBRARY
    NAMES tf3
    PATHS /usr/lib /usr/local/lib /usr/lib/x86_64-linux-gnu
  )

  if(NOT TF3_LIBRARY)
    message(FATAL_ERROR "❌ tf3 library not found")
  endif()

  catkin_package(
    INCLUDE_DIRS include
    LIBRARIES ${PROJECT_NAME}
    CATKIN_DEPENDS
      cv_bridge
      robot_sensor_msgs
      robot_cpp
      data_convert
      robot_image_geometry
      roscpp
      sensor_msgs
      std_msgs
      tf2_ros
    DEPENDS Boost Eigen3
  )

  include_directories(
    include
    ${catkin_INCLUDE_DIRS}
    ${Boost_INCLUDE_DIRS}
  )

endif()

# ========================================================
# Check headers
# ========================================================
include(CheckIncludeFile)

check_include_file(sys/time.h HAVE_SYS_TIME_H)

if(HAVE_SYS_TIME_H)
  add_definitions(-DHAVE_SYS_TIME_H)
endif()

# ========================================================
# Library
# ========================================================
add_library(${PROJECT_NAME} SHARED
  src/point_cloud_xyz.cpp
  src/depth_frame_filter.cpp
)

# ========================================================
# Catkin linking
# ========================================================
if(BUILDING_WITH_CATKIN)

  add_dependencies(${PROJECT_NAME}
    ${catkin_EXPORTED_TARGETS}
  )

  target_include_directories(${PROJECT_NAME}
    PUBLIC
      $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
      $<INSTALL_INTERFACE:include>
  )

  target_link_libraries(${PROJECT_NAME}

    PUBLIC
      ${catkin_LIBRARIES}

    PRIVATE
      Boost::thread
      Eigen3::Eigen
      ${TF3_LIBRARY}
  )

# ========================================================
# Standalone linking
# ========================================================
else()

  target_include_directories(${PROJECT_NAME}
    PUBLIC
      $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
      $<INSTALL_INTERFACE:include>
  )

  target_link_libraries(${PROJECT_NAME}

    PUBLIC
      ${PACKAGES_DIR}

    PRIVATE
      Boost::thread
      Eigen3::Eigen
      ${TF3_LIBRARY}
  )

  set_target_properties(${PROJECT_NAME} PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
    BUILD_RPATH "${CMAKE_BINARY_DIR}"
    INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib"
  )

endif()

# ========================================================
# Test node + unit tests
# ========================================================
if(BUILDING_WITH_CATKIN)

  add_executable(depth_image_proc_test_node
    src/depth_image_proc_test_node.cpp
  )

  add_dependencies(depth_image_proc_test_node
    ${catkin_EXPORTED_TARGETS}
  )

  target_include_directories(depth_image_proc_test_node PRIVATE
    include
    ${catkin_INCLUDE_DIRS}
  )

  target_link_libraries(depth_image_proc_test_node
    ${PROJECT_NAME}
    ${catkin_LIBRARIES}
  )

  add_executable(depth_image_proc_node
    src/depth_image_proc_node.cpp
  )

  add_dependencies(depth_image_proc_node
    ${catkin_EXPORTED_TARGETS}
  )

  target_include_directories(depth_image_proc_node PRIVATE
    include
    ${catkin_INCLUDE_DIRS}
  )

  target_link_libraries(depth_image_proc_node
    ${PROJECT_NAME}
    ${catkin_LIBRARIES}
  )

  install(TARGETS depth_image_proc_test_node depth_image_proc_node
    RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
  )

  install(DIRECTORY launch rviz
    DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
  )

  if(CATKIN_ENABLE_TESTING)
    find_package(GTest REQUIRED)

    catkin_add_gtest(test_point_cloud_xyz
      test/test_point_cloud_xyz.cpp
    )

    if(TARGET test_point_cloud_xyz)
      target_include_directories(test_point_cloud_xyz PRIVATE
        include
        ${catkin_INCLUDE_DIRS}
      )

      target_link_libraries(test_point_cloud_xyz
        ${PROJECT_NAME}
        ${catkin_LIBRARIES}
        GTest::GTest
        GTest::Main
      )
    endif()
  endif()

endif()

# ========================================================
# Install
# ========================================================
if(BUILDING_WITH_CATKIN)

  install(TARGETS ${PROJECT_NAME}

    ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
    LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
    RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
  )

  install(DIRECTORY include/${PROJECT_NAME}/
    DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
    FILES_MATCHING PATTERN "*.h"
  )

else()

  install(TARGETS ${PROJECT_NAME}
    EXPORT ${PROJECT_NAME}-targets
    ARCHIVE DESTINATION lib
    LIBRARY DESTINATION lib
    RUNTIME DESTINATION bin
  )

  install(EXPORT ${PROJECT_NAME}-targets
    FILE ${PROJECT_NAME}-targets.cmake
    NAMESPACE ${PROJECT_NAME}::
    DESTINATION lib/cmake/${PROJECT_NAME}
  )

  install(DIRECTORY include/${PROJECT_NAME}/
    DESTINATION include
    FILES_MATCHING PATTERN "*.h"
  )

endif()
