cmake_minimum_required(VERSION 3.16)
project(_p2pstream_core CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()

include(CheckCXXCompilerFlag)

check_cxx_compiler_flag("-O3" HAS_O3)
if(HAS_O3)
  add_compile_options($<$<CONFIG:Release>:-O3>)
endif()

check_cxx_compiler_flag("-mfpu=neon" HAS_NEON)
if(HAS_NEON AND CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
  add_compile_options($<$<CONFIG:Release>:-mfpu=neon>)
  add_compile_definitions(HAS_NEON)
endif()

check_cxx_compiler_flag("-msse4.2" HAS_SSE42)
if(HAS_SSE42 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86|AMD64|x86_64")
  add_compile_options($<$<CONFIG:Release>:-msse4.2>)
  add_compile_definitions(HAS_SSE42)
endif()

find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
execute_process(
  COMMAND "${Python3_EXECUTABLE}" -c "import pybind11; print(pybind11.get_cmake_dir())"
  OUTPUT_VARIABLE PYBIND11_CMAKE_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
  RESULT_VARIABLE _pb11_rc)
if(NOT _pb11_rc EQUAL 0)
  message(FATAL_ERROR "pybind11 not found: pip install pybind11")
endif()
list(APPEND CMAKE_PREFIX_PATH "${PYBIND11_CMAKE_DIR}")
find_package(pybind11 REQUIRED CONFIG)
find_package(OpenSSL REQUIRED)

find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
  pkg_check_modules(LZ4 QUIET liblz4)
endif()
if(NOT LZ4_FOUND)
  find_library(LZ4_LIB lz4)
  find_path(LZ4_INC lz4.h)
  if(LZ4_LIB AND LZ4_INC)
    set(LZ4_LIBRARIES ${LZ4_LIB})
    set(LZ4_INCLUDE_DIRS ${LZ4_INC})
    set(LZ4_FOUND TRUE)
  endif()
endif()

find_library(MINIUPNPC_LIB miniupnpc)
find_path(MINIUPNPC_INC miniupnpc/miniupnpc.h)

pybind11_add_module(_p2pstream_core MODULE
  codec.cpp fec.cpp abr.cpp nat_traversal.cpp bindings.cpp)

target_include_directories(_p2pstream_core PRIVATE
  ${CMAKE_CURRENT_SOURCE_DIR} ${OPENSSL_INCLUDE_DIR})
target_link_libraries(_p2pstream_core PRIVATE OpenSSL::Crypto)

if(LZ4_FOUND)
  target_include_directories(_p2pstream_core PRIVATE ${LZ4_INCLUDE_DIRS})
  target_link_libraries(_p2pstream_core PRIVATE ${LZ4_LIBRARIES})
  target_compile_definitions(_p2pstream_core PRIVATE HAS_LZ4)
  message(STATUS "LZ4: ON")
else()
  message(STATUS "LZ4: OFF (pass-through)")
endif()

if(MINIUPNPC_LIB AND MINIUPNPC_INC)
  target_include_directories(_p2pstream_core PRIVATE ${MINIUPNPC_INC})
  target_link_libraries(_p2pstream_core PRIVATE ${MINIUPNPC_LIB})
  target_compile_definitions(_p2pstream_core PRIVATE HAS_MINIUPNPC)
  message(STATUS "miniupnpc: ON")
else()
  message(STATUS "miniupnpc: OFF")
endif()

if(UNIX)
  target_link_libraries(_p2pstream_core PRIVATE pthread)
endif()
