# ── Dependencies.cmake ───────────────────────────────────────────
# Central location for all external library paths.
# Adjust these paths per platform.
# ─────────────────────────────────────────────────────────────────

# ── Platform-specific base paths ────────────────────────────────
if(WIN32)
    set(ANSLIBS_DIR      "C:/ANSLibs"                          CACHE PATH "Root of ANS external libraries")
    set(ANLS_ROOT        "C:/Projects/ANLS"                    CACHE PATH "Original ANLS project root")
    set(RESEARCH_DIR     "C:/Projects/Research/CPlusLibraries" CACHE PATH "Research libraries root")
elseif(APPLE)
    set(ANSLIBS_DIR      "$ENV{HOME}/ANSLibs"                  CACHE PATH "Root of ANS external libraries")
    set(ANLS_ROOT        "$ENV{HOME}/Projects/ANLS"            CACHE PATH "Original ANLS project root")
    set(RESEARCH_DIR     "$ENV{HOME}/Projects/Research/CPlusLibraries" CACHE PATH "Research libraries root")
else() # Linux
    set(ANSLIBS_DIR      "/opt/ANSLibs"                        CACHE PATH "Root of ANS external libraries")
    set(ANLS_ROOT        "$ENV{HOME}/Projects/ANLS"            CACHE PATH "Original ANLS project root")
    set(RESEARCH_DIR     "$ENV{HOME}/Projects/Research/CPlusLibraries" CACHE PATH "Research libraries root")
endif()

# ── Platform library suffix helper ──────────────────────────────
if(WIN32)
    set(LIB_SUFFIX ".lib")
    set(SHARED_SUFFIX ".dll")
else()
    set(LIB_SUFFIX "")       # CMake handles -l prefix on Unix
    set(SHARED_SUFFIX ".so")
    if(APPLE)
        set(SHARED_SUFFIX ".dylib")
    endif()
endif()

# ── CUDA (optional) ────────────────────────────────────────────
if(ANSCORE_HAS_CUDA)
    find_package(CUDAToolkit REQUIRED)
endif()

# ── OpenCV ──────────────────────────────────────────────────────
# On Windows: skip find_package(OpenCV) — its bundled OpenCVConfig.cmake
# calls legacy find_package(CUDA) which fails with modern CMake.
# On Linux/Mac: try system-installed OpenCV first.
if(NOT WIN32)
    find_package(OpenCV QUIET)
endif()
if(OpenCV_FOUND)
    add_library(opencv INTERFACE)
    target_link_libraries(opencv INTERFACE ${OpenCV_LIBS})
    target_include_directories(opencv INTERFACE ${OpenCV_INCLUDE_DIRS})
    message(STATUS "OpenCV: using system install (${OpenCV_VERSION})")
else()
    set(OPENCV_INCLUDE_DIR "${ANSLIBS_DIR}/opencv/include")
    set(OPENCV_LIB_DIR     "${ANSLIBS_DIR}/opencv/x64/vc17/lib")
    add_library(opencv INTERFACE)
    target_include_directories(opencv INTERFACE ${OPENCV_INCLUDE_DIR})
    target_link_directories(opencv INTERFACE ${OPENCV_LIB_DIR})
    if(WIN32)
        target_link_libraries(opencv INTERFACE
            optimized opencv_world4130.lib
            optimized opencv_img_hash4130.lib
            debug opencv_world4130d.lib
            debug opencv_img_hash4130d.lib
        )
    else()
        # Linux/Mac: link individual modules or opencv_world
        target_link_libraries(opencv INTERFACE
            opencv_world
            opencv_img_hash
        )
    endif()
    message(STATUS "OpenCV: using ANSLibs at ${OPENCV_INCLUDE_DIR}")
endif()

# ── ONNX Runtime ────────────────────────────────────────────────
set(ONNXRT_INCLUDE_DIR "${ANSLIBS_DIR}/onnxruntime/include")
set(ONNXRT_LIB_DIR     "${ANSLIBS_DIR}/onnxruntime/lib")

add_library(onnxruntime INTERFACE)
target_include_directories(onnxruntime INTERFACE ${ONNXRT_INCLUDE_DIR})
target_link_directories(onnxruntime INTERFACE ${ONNXRT_LIB_DIR})
if(WIN32)
    target_link_libraries(onnxruntime INTERFACE onnxruntime.lib)
else()
    target_link_libraries(onnxruntime INTERFACE onnxruntime)
endif()
target_compile_definitions(onnxruntime INTERFACE ORT_API_MANUAL_INIT)

# ── TensorRT (Windows + Linux only) ────────────────────────────
if(NOT APPLE)
    set(TENSORRT_INCLUDE_DIR "${ANSLIBS_DIR}/TensorRT/include")
    set(TENSORRT_LIB_DIR     "${ANSLIBS_DIR}/TensorRT/lib")

    add_library(tensorrt INTERFACE)
    target_include_directories(tensorrt INTERFACE ${TENSORRT_INCLUDE_DIR})
    target_link_directories(tensorrt INTERFACE ${TENSORRT_LIB_DIR})
    if(WIN32)
        target_link_libraries(tensorrt INTERFACE nvinfer_plugin_10.lib)
    else()
        target_link_libraries(tensorrt INTERFACE nvinfer_plugin)
    endif()
endif()

# ── OpenVINO (Windows + Linux, x86_64 only) ────────────────────
if(NOT APPLE)
    set(OPENVINO_INCLUDE_DIR "${ANSLIBS_DIR}/OpenVINO/runtime/include")
    if(WIN32)
        set(OPENVINO_LIB_DIR "${ANSLIBS_DIR}/OpenVINO/runtime/lib/intel64/Release")
    else()
        set(OPENVINO_LIB_DIR "${ANSLIBS_DIR}/OpenVINO/runtime/lib/intel64")
    endif()

    add_library(openvino INTERFACE)
    target_include_directories(openvino INTERFACE ${OPENVINO_INCLUDE_DIR})
    target_link_directories(openvino INTERFACE ${OPENVINO_LIB_DIR})
    if(WIN32)
        target_link_libraries(openvino INTERFACE openvino.lib)
    else()
        target_link_libraries(openvino INTERFACE openvino)
    endif()
endif()

# ── Python 3 + pybind11 ────────────────────────────────────────
if(WIN32)
    set(PYTHON_INCLUDE_DIR   "${ANSLIBS_DIR}/Python311/include")
    set(PYTHON_LIB_DIR       "${ANSLIBS_DIR}/Python311/libs")
    set(PYBIND11_INCLUDE_DIR "${ANSLIBS_DIR}/pybind11/include")

    add_library(python311 INTERFACE)
    target_include_directories(python311 INTERFACE ${PYTHON_INCLUDE_DIR} ${PYBIND11_INCLUDE_DIR})
    target_link_directories(python311 INTERFACE ${PYTHON_LIB_DIR})
    target_link_libraries(python311 INTERFACE python311.lib)
else()
    # Use system Python on Linux/Mac
    find_package(Python3 COMPONENTS Development)
    add_library(python311 INTERFACE)
    if(Python3_FOUND)
        target_include_directories(python311 INTERFACE ${Python3_INCLUDE_DIRS})
        target_link_libraries(python311 INTERFACE ${Python3_LIBRARIES})
    endif()
    # pybind11 via system install or ANSLibs
    find_package(pybind11 QUIET)
    if(pybind11_FOUND)
        target_link_libraries(python311 INTERFACE pybind11::headers)
    elseif(EXISTS "${ANSLIBS_DIR}/pybind11/include")
        target_include_directories(python311 INTERFACE "${ANSLIBS_DIR}/pybind11/include")
    endif()
endif()

# ── Boost ───────────────────────────────────────────────────────
find_package(Boost QUIET)
if(Boost_FOUND)
    add_library(boost INTERFACE)
    target_link_libraries(boost INTERFACE Boost::headers)
    message(STATUS "Boost: using system install")
else()
    set(BOOST_INCLUDE_DIR "${ANSLIBS_DIR}/boost/include")
    set(BOOST_LIB_DIR     "${ANSLIBS_DIR}/boost/lib")
    add_library(boost INTERFACE)
    target_include_directories(boost INTERFACE ${BOOST_INCLUDE_DIR})
    target_link_directories(boost INTERFACE ${BOOST_LIB_DIR})
    message(STATUS "Boost: using ANSLibs at ${BOOST_INCLUDE_DIR}")
endif()

# ── FFmpeg ──────────────────────────────────────────────────────
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
    pkg_check_modules(FFMPEG QUIET libavcodec libavformat libavutil libswscale)
endif()

if(FFMPEG_FOUND)
    add_library(ffmpeg INTERFACE)
    target_include_directories(ffmpeg INTERFACE ${FFMPEG_INCLUDE_DIRS})
    target_link_directories(ffmpeg INTERFACE ${FFMPEG_LIBRARY_DIRS})
    target_link_libraries(ffmpeg INTERFACE ${FFMPEG_LIBRARIES})
    message(STATUS "FFmpeg: using system install")
else()
    set(FFMPEG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/MediaClient/ffmpeg/include")
    set(FFMPEG_LIB_DIR     "${CMAKE_SOURCE_DIR}/MediaClient/ffmpeg/lib/x64")
    add_library(ffmpeg INTERFACE)
    target_include_directories(ffmpeg INTERFACE ${FFMPEG_INCLUDE_DIR})
    target_link_directories(ffmpeg INTERFACE ${FFMPEG_LIB_DIR})
    if(WIN32)
        target_link_libraries(ffmpeg INTERFACE
            avcodec.lib avdevice.lib avfilter.lib avformat.lib
            avutil.lib postproc.lib swresample.lib swscale.lib
        )
    else()
        target_link_libraries(ffmpeg INTERFACE
            avcodec avdevice avfilter avformat
            avutil postproc swresample swscale
        )
    endif()
    message(STATUS "FFmpeg: using ANSLibs at ${FFMPEG_INCLUDE_DIR}")
endif()

# ── TurboJPEG ───────────────────────────────────────────────────
add_library(turbojpeg INTERFACE)
if(WIN32)
    target_include_directories(turbojpeg INTERFACE "${ANLS_ROOT}/TurboJpeg")
    target_link_directories(turbojpeg INTERFACE "${ANLS_ROOT}/TurboJpeg")
    target_link_libraries(turbojpeg INTERFACE turbojpeg-static.lib)
else()
    find_library(TURBOJPEG_LIB turbojpeg)
    if(TURBOJPEG_LIB)
        target_link_libraries(turbojpeg INTERFACE ${TURBOJPEG_LIB})
    else()
        target_link_directories(turbojpeg INTERFACE "${ANSLIBS_DIR}/turbojpeg/lib")
        target_link_libraries(turbojpeg INTERFACE turbojpeg)
    endif()
endif()

# ── FAISS (Facebook AI Similarity Search) ───────────────────────
set(FAISS_INCLUDE_DIR "${ANSLIBS_DIR}/faiss/include")
set(FAISS_LIB_DIR     "${ANSLIBS_DIR}/faiss/lib")

add_library(faiss INTERFACE)
target_include_directories(faiss INTERFACE ${FAISS_INCLUDE_DIR})
target_link_directories(faiss INTERFACE ${FAISS_LIB_DIR})
if(WIN32)
    target_link_libraries(faiss INTERFACE faiss.lib)
else()
    target_link_libraries(faiss INTERFACE faiss)
endif()

# ── Intel MKL ───────────────────────────────────────────────────
add_library(mkl INTERFACE)
if(WIN32)
    set(MKL_LIB_DIR "C:/Program Files (x86)/Intel/oneAPI/mkl/2025.0/lib")
    target_link_directories(mkl INTERFACE "${MKL_LIB_DIR}")
    target_link_libraries(mkl INTERFACE mkl_rt.lib)
else()
    # Try system MKL on Linux
    find_library(MKL_RT_LIB mkl_rt PATHS /opt/intel/oneapi/mkl/latest/lib/intel64)
    if(MKL_RT_LIB)
        target_link_libraries(mkl INTERFACE ${MKL_RT_LIB})
    endif()
endif()

# ── Chilkat (HTTP/AWS) ──────────────────────────────────────────
add_library(chilkat INTERFACE)
if(WIN32)
    set(CHILKAT_INCLUDE_DIR "${RESEARCH_DIR}/chilkat/include")
    set(CHILKAT_LIB_DIR     "${RESEARCH_DIR}/chilkat/libs")
    target_include_directories(chilkat INTERFACE ${CHILKAT_INCLUDE_DIR})
    target_link_directories(chilkat INTERFACE ${CHILKAT_LIB_DIR})
    target_link_libraries(chilkat INTERFACE ChilkatRel_x64.lib)
else()
    # Chilkat has Linux builds — set paths when available
    if(EXISTS "${ANSLIBS_DIR}/chilkat/include")
        target_include_directories(chilkat INTERFACE "${ANSLIBS_DIR}/chilkat/include")
        target_link_directories(chilkat INTERFACE "${ANSLIBS_DIR}/chilkat/lib")
        target_link_libraries(chilkat INTERFACE chilkat)
    endif()
endif()

# ── ZXing (QR Code) ────────────────────────────────────────────
add_library(zxing INTERFACE)
if(WIN32)
    set(ZXING_INCLUDE_DIR "${RESEARCH_DIR}/QRCode")
    set(ZXING_LIB_DIR     "${RESEARCH_DIR}/QRCode")
    target_include_directories(zxing INTERFACE ${ZXING_INCLUDE_DIR})
    target_link_directories(zxing INTERFACE ${ZXING_LIB_DIR})
    target_link_libraries(zxing INTERFACE ZXing.lib)
else()
    find_package(ZXing QUIET)
    if(ZXing_FOUND)
        target_link_libraries(zxing INTERFACE ZXing::ZXing)
    endif()
endif()

# ── LabVIEW (Windows only) ─────────────────────────────────────
add_library(labview INTERFACE)
if(WIN32)
    # Code uses #include "LabVIEWHeader/extcode.h", so include the parent dir
    set(LABVIEW_INCLUDE_DIR "${RESEARCH_DIR}")
    set(LABVIEW_LIB_DIR     "${RESEARCH_DIR}/LabVIEWHeader")
    target_include_directories(labview INTERFACE ${LABVIEW_INCLUDE_DIR})
    target_link_directories(labview INTERFACE ${LABVIEW_LIB_DIR})
    target_link_libraries(labview INTERFACE labview-x86_64.lib)
endif()

# ── spdlog ──────────────────────────────────────────────────────
find_package(spdlog QUIET)
if(spdlog_FOUND)
    add_library(spdlog_dep INTERFACE)
    target_link_libraries(spdlog_dep INTERFACE spdlog::spdlog)
else()
    add_library(spdlog_dep INTERFACE)
    if(EXISTS "${RESEARCH_DIR}/spdlog-1.12.0/include")
        target_include_directories(spdlog_dep INTERFACE "${RESEARCH_DIR}/spdlog-1.12.0/include")
    elseif(EXISTS "${ANSLIBS_DIR}/spdlog/include")
        target_include_directories(spdlog_dep INTERFACE "${ANSLIBS_DIR}/spdlog/include")
    endif()
endif()

# ── vcpkg installed libs ────────────────────────────────────────
if(WIN32)
    set(VCPKG_INCLUDE_DIR "${RESEARCH_DIR}/vcpkg/installed/x64-windows/include")
    set(VCPKG_LIB_DIR     "${RESEARCH_DIR}/vcpkg/installed/x64-windows/lib")
    add_library(vcpkg_libs INTERFACE)
    target_include_directories(vcpkg_libs INTERFACE ${VCPKG_INCLUDE_DIR})
    target_link_directories(vcpkg_libs INTERFACE ${VCPKG_LIB_DIR})
endif()

# ── zlib ────────────────────────────────────────────────────────
add_library(zlib_dep INTERFACE)
if(WIN32)
    target_include_directories(zlib_dep INTERFACE "${ANSLIBS_DIR}/ZLIB/include")
    target_link_directories(zlib_dep INTERFACE "${ANSLIBS_DIR}/ZLIB/lib")
    target_link_libraries(zlib_dep INTERFACE zlibstatic.lib)
else()
    find_package(ZLIB REQUIRED)
    target_link_libraries(zlib_dep INTERFACE ZLIB::ZLIB)
endif()

# ── Common link libraries ──────────────────────────────────────
if(WIN32)
    set(WIN_COMMON_LIBS ws2_32 winmm shlwapi iphlpapi crypt32)
else()
    set(WIN_COMMON_LIBS "")  # Empty on Unix — use pthreads/dl instead
    find_package(Threads REQUIRED)
    set(UNIX_COMMON_LIBS Threads::Threads ${CMAKE_DL_LIBS})
endif()

# ── Shared source directories ─────────────────────────────────
set(SHARED_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include")
