# Determine which Python to use
# Priority: user-specified PYTHON3_EXECUTABLE > python3 in PATH > python in PATH > CMake FindPython3
# This allows automatic detection in conda/virtualenv environments
if(DEFINED PYTHON3_EXECUTABLE AND EXISTS "${PYTHON3_EXECUTABLE}")
    set(DLDT_PYTHON_EXECUTABLE "${PYTHON3_EXECUTABLE}")
    message(STATUS "Using user-specified Python: ${PYTHON3_EXECUTABLE}")
elseif(NOT DLDT_PYTHON_EXECUTABLE)
    # Try to find python3 in PATH (works in conda/virtualenv)
    find_program(PYTHON3_IN_PATH NAMES python3 python)
    if(PYTHON3_IN_PATH)
        # Verify it's Python 3
        execute_process(
            COMMAND "${PYTHON3_IN_PATH}" -c "import sys; sys.exit(0 if sys.version_info[0] == 3 else 1)"
            RESULT_VARIABLE IS_PYTHON3
            ERROR_QUIET
        )
        if(IS_PYTHON3 EQUAL 0)
            set(DLDT_PYTHON_EXECUTABLE "${PYTHON3_IN_PATH}")
            message(STATUS "Using Python from PATH: ${PYTHON3_IN_PATH}")
        endif()
    endif()
endif()

# Fallback to CMake's FindPython3 if still not found
if(NOT DLDT_PYTHON_EXECUTABLE)
    find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
    set(DLDT_PYTHON_EXECUTABLE "${Python3_EXECUTABLE}")
    message(STATUS "Using system Python (fallback): ${Python3_EXECUTABLE}")
endif()

# Get Python include and library directories
execute_process(
    COMMAND "${DLDT_PYTHON_EXECUTABLE}" -c "import sysconfig; print(sysconfig.get_path('include'))"
    OUTPUT_VARIABLE Python3_INCLUDE_DIRS
    OUTPUT_STRIP_TRAILING_WHITESPACE
    ERROR_QUIET
)
execute_process(
    COMMAND "${DLDT_PYTHON_EXECUTABLE}" -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"
    OUTPUT_VARIABLE Python3_LIBRARY_DIRS
    OUTPUT_STRIP_TRAILING_WHITESPACE
    ERROR_QUIET
)

# Find pybind11 using the detected Python
# Always use the same Python to ensure version compatibility
execute_process(
    COMMAND "${DLDT_PYTHON_EXECUTABLE}" -c "import pybind11; print(pybind11.get_cmake_dir())"
    OUTPUT_VARIABLE PYBIND11_CMAKE_DIR
    OUTPUT_STRIP_TRAILING_WHITESPACE
    ERROR_QUIET
)
if(EXISTS "${PYBIND11_CMAKE_DIR}")
    list(APPEND CMAKE_PREFIX_PATH "${PYBIND11_CMAKE_DIR}")
    find_package(pybind11 REQUIRED)
    message(STATUS "Found pybind11 via Python: ${PYBIND11_CMAKE_DIR}")
else()
    message(FATAL_ERROR
        "pybind11 not found (required for BUILD_PYDLDT).\n"
        "  Please install: ${DLDT_PYTHON_EXECUTABLE} -m pip install pybind11\n"
        "  Or disable: cmake -DBUILD_PYDLDT=OFF ..."
    )
endif()

# Get SDK path from environment
if(NOT DEFINED ENV{DLICC_PATH})
    message(WARNING "DLICC_PATH not set. Python bindings may not build correctly.")
else()
    get_filename_component(SDK_PATH "$ENV{DLICC_PATH}/../" ABSOLUTE)
    include_directories(${SDK_PATH}/include)
    link_directories(${SDK_PATH}/lib)
endif()

# Include dldt headers
set(DLDT_REPO_DIR ${CMAKE_SOURCE_DIR})
include_directories(
    ${DLDT_REPO_DIR}/dldt
    ${DLDT_REPO_DIR}/dldt/jpeg
    ${DLDT_REPO_DIR}/dldt/video
    ${DLDT_REPO_DIR}/dldt/network
)

# Find FFmpeg (only if BUILD_VIDEO is enabled)
# Custom FFmpeg path is handled in root CMakeLists.txt
if(BUILD_VIDEO)
    find_package(PkgConfig QUIET)
    if(PKG_CONFIG_FOUND)
        pkg_check_modules(LIBAV REQUIRED
            libavcodec
            libavformat
            libavutil
        )
        if(LIBAV_FOUND)
            if(DEFINED FFMPEG_ROOT AND NOT FFMPEG_ROOT STREQUAL "")
                message(STATUS "Found FFmpeg (custom): ${FFMPEG_ROOT}")
            else()
                message(STATUS "Found FFmpeg: ${LIBAV_INCLUDE_DIRS}")
            endif()
        else()
            message(WARNING "FFmpeg not found via pkg-config, trying system paths")
        endif()
    endif()
else()
    message(STATUS "Video modules disabled, skipping FFmpeg detection")
endif()

# =============================================================================
# Common source file collections (for modules that need them)
# =============================================================================
set(FFMPEG_LIBS avformat avcodec swscale swresample avutil)

# Source files for JPEG module (no FFmpeg dependency)
set(DLDT_JPEG_MODULE_SOURCES
    ${DLDT_REPO_DIR}/dldt/jpeg/jpeg_decoder.cc
    ${DLDT_REPO_DIR}/dldt/jpeg/jpeg_encoder.cc
)

# Source files for Video modules (requires FFmpeg)
set(DLDT_VIDEO_MODULE_SOURCES
    ${DLDT_REPO_DIR}/dldt/video/video_common.cc
    ${DLDT_REPO_DIR}/dldt/video/video_decoder.cc
    ${DLDT_REPO_DIR}/dldt/video/video_encoder.cc
    ${DLDT_REPO_DIR}/dldt/video/ffmpeg_demuxer.cc
    ${DLDT_REPO_DIR}/dldt/video/ffmpeg_muxer.cc
)

# =============================================================================
# pydldt_video_decode - Video decoder/demuxer (requires FFmpeg)
# =============================================================================
if(BUILD_VIDEO)
pybind11_add_module(pydldt_video_decode
    video_decoder_python.cc
    ${DLDT_VIDEO_MODULE_SOURCES}
)
target_compile_definitions(pydldt_video_decode PRIVATE dldt_video_EXPORTS)

target_include_directories(pydldt_video_decode PRIVATE
    ${Python3_INCLUDE_DIRS}
)

if(pybind11_FOUND)
    target_include_directories(pydldt_video_decode PRIVATE ${pybind11_INCLUDE_DIRS})
else()
    target_include_directories(pydldt_video_decode PRIVATE ${PYBIND11_INCLUDE_DIR})
endif()

if(LIBAV_FOUND)
    target_include_directories(pydldt_video_decode PRIVATE ${LIBAV_INCLUDE_DIRS})
endif()

target_link_libraries(pydldt_video_decode PRIVATE
    dlvid       # Video library
    curt        # CUDA runtime
    ${FFMPEG_LIBS}
)

set_target_properties(pydldt_video_decode PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pydldt"
    PREFIX "py"
    OUTPUT_NAME "dldt_video_decode"
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)
endif()

# =============================================================================
# pydldt_cuda - CUDA runtime (no dldt C++ sources)
# =============================================================================
pybind11_add_module(pydldt_cuda
    cuda_python.cc
)

target_include_directories(pydldt_cuda PRIVATE
    ${Python3_INCLUDE_DIRS}
)

if(pybind11_FOUND)
    target_include_directories(pydldt_cuda PRIVATE ${pybind11_INCLUDE_DIRS})
else()
    target_include_directories(pydldt_cuda PRIVATE ${PYBIND11_INCLUDE_DIR})
endif()

target_link_libraries(pydldt_cuda PRIVATE
    curt        # CUDA runtime
)

set_target_properties(pydldt_cuda PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pydldt"
    PREFIX "py"
    OUTPUT_NAME "dldt_cuda"
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)

# =============================================================================
# pydldt_cuda_kernel_impl - CUDA kernels (requires BUILD_CUDA_KERNEL)
# =============================================================================
if(BUILD_CUDA_KERNEL)
pybind11_add_module(pydldt_cuda_kernel_impl
    dldt_cuda_kernel_python.cc
)

target_include_directories(pydldt_cuda_kernel_impl PRIVATE
    ${Python3_INCLUDE_DIRS}
    ${DLDT_REPO_DIR}/dldt_cuda_kernel/include
)

if(pybind11_FOUND)
    target_include_directories(pydldt_cuda_kernel_impl PRIVATE ${pybind11_INCLUDE_DIRS})
else()
    target_include_directories(pydldt_cuda_kernel_impl PRIVATE ${PYBIND11_INCLUDE_DIR})
endif()

target_link_libraries(pydldt_cuda_kernel_impl PRIVATE
    curt                # CUDA runtime
    dldt_cuda_kernel    # CUDA kernel library
)

set_target_properties(pydldt_cuda_kernel_impl PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pydldt"
    PREFIX "py"
    OUTPUT_NAME "cuda_kernel_impl"
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)
endif()

# =============================================================================
# pydldt_video_encode - Video encoder/muxer (requires FFmpeg)
# =============================================================================
if(BUILD_VIDEO)
pybind11_add_module(pydldt_video_encode
    video_encoder_python.cc
    ${DLDT_VIDEO_MODULE_SOURCES}
)
target_compile_definitions(pydldt_video_encode PRIVATE dldt_video_EXPORTS)

target_include_directories(pydldt_video_encode PRIVATE
    ${Python3_INCLUDE_DIRS}
)

if(pybind11_FOUND)
    target_include_directories(pydldt_video_encode PRIVATE ${pybind11_INCLUDE_DIRS})
else()
    target_include_directories(pydldt_video_encode PRIVATE ${PYBIND11_INCLUDE_DIR})
endif()

if(LIBAV_FOUND)
    target_include_directories(pydldt_video_encode PRIVATE ${LIBAV_INCLUDE_DIRS})
endif()

target_link_libraries(pydldt_video_encode PRIVATE
    dlvid       # Video library
    curt        # CUDA runtime
    ${FFMPEG_LIBS}
)

set_target_properties(pydldt_video_encode PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pydldt"
    PREFIX "py"
    OUTPUT_NAME "dldt_video_encode"
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)
endif()

# =============================================================================
# pydldt_jpeg - JPEG codec (no FFmpeg dependency)
# =============================================================================
if(BUILD_JPEG)
pybind11_add_module(pydldt_jpeg
    jpeg_python.cc
    ${DLDT_JPEG_MODULE_SOURCES}
)
target_compile_definitions(pydldt_jpeg PRIVATE dldt_jpeg_EXPORTS)

target_include_directories(pydldt_jpeg PRIVATE
    ${Python3_INCLUDE_DIRS}
)

if(pybind11_FOUND)
    target_include_directories(pydldt_jpeg PRIVATE ${pybind11_INCLUDE_DIRS})
else()
    target_include_directories(pydldt_jpeg PRIVATE ${PYBIND11_INCLUDE_DIR})
endif()

target_link_libraries(pydldt_jpeg PRIVATE
    curt        # CUDA runtime
    dljpeg     # JPEG library
)

set_target_properties(pydldt_jpeg PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pydldt"
    PREFIX "py"
    OUTPUT_NAME "dldt_jpeg"
    CXX_STANDARD 17
    CXX_STANDARD_REQUIRED ON
    CXX_EXTENSIONS OFF
)
endif()

# =============================================================================
# Installation
# =============================================================================
set(INSTALL_TARGETS pydldt_cuda)
if(BUILD_JPEG)
    list(APPEND INSTALL_TARGETS pydldt_jpeg)
endif()
if(BUILD_VIDEO)
    list(APPEND INSTALL_TARGETS pydldt_video_decode pydldt_video_encode)
endif()
if(BUILD_CUDA_KERNEL)
    list(APPEND INSTALL_TARGETS pydldt_cuda_kernel_impl)
endif()

install(TARGETS ${INSTALL_TARGETS}
    LIBRARY DESTINATION python/dldt
    RUNTIME DESTINATION python/dldt
)

# Install Python package files (pure Python modules)
# Install pydldt/dldt/ to python/dldt/
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dldt/
    DESTINATION python/dldt
    FILES_MATCHING PATTERN "*.py"
)

# =============================================================================
# Configuration Summary
# =============================================================================
message(STATUS "")
message(STATUS "=================================")
message(STATUS "pydldt Configuration Summary")
message(STATUS "=================================")
message(STATUS "Python:              ${DLDT_PYTHON_EXECUTABLE}")
message(STATUS "Python Include:      ${Python3_INCLUDE_DIRS}")
message(STATUS "pybind11:            ${pybind11_INCLUDE_DIRS}")
if(DEFINED SDK_PATH)
    message(STATUS "SDK Path:            ${SDK_PATH}")
endif()
if(LIBAV_FOUND)
    message(STATUS "FFmpeg:              Found (${LIBAV_INCLUDE_DIRS})")
else()
    message(STATUS "FFmpeg:              Not found (using system paths)")
endif()
message(STATUS "")
message(STATUS "Python Modules:")
if(BUILD_JPEG)
    message(STATUS "  pydldt_jpeg         - JPEG codec")
endif()
if(BUILD_VIDEO)
    message(STATUS "  pydldt_video_decode  - Video decoder/demuxer")
    message(STATUS "  pydldt_video_encode  - Video encoder/muxer")
endif()
message(STATUS "  pydldt_cuda         - CUDA runtime")
if(BUILD_CUDA_KERNEL)
    message(STATUS "  pydldt_cuda_kernel_impl - CUDA kernels (conditional)")
endif()
message(STATUS "")
message(STATUS "Module Output Directory:")
message(STATUS "  Build:  ${CMAKE_BINARY_DIR}/pydldt")
message(STATUS "  Install: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_PYTHONDIR}")
message(STATUS "=================================")
message(STATUS "")
