# SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
# SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
# SPDX-License-Identifier: BSD-3-Clause

# this is set in the parent directory, but for some reason it does not get inherited
set_source_files_properties(${SWIG_BINDINGS_SOURCE_FILE} PROPERTIES CPLUSPLUS ON)

set(CMAKE_SWIG_FLAGS "-module;yarp;-threads;${SWIG_COMMON_FLAGS}")

# https://github.com/pybind/pybind11/pull/2689
if(${CMAKE_VERSION} VERSION_LESS "3.18.0")
  set(YARP_Python_Development_Component "Development")
else()
  set(YARP_Python_Development_Component "Development.Module")
endif()

find_package(Python3 COMPONENTS Interpreter ${YARP_Python_Development_Component} REQUIRED)

set(CMAKE_SWIG_OUTDIR "${CMAKE_BINARY_DIR}/lib/python3")
set(SWIG_OUTFILE_DIR "${CMAKE_CURRENT_BINARY_DIR}")

if(${CMAKE_VERSION} VERSION_LESS "3.15.0")
  set(YARP_Python_Module_Target "Python3::Python")
else()
  set(YARP_Python_Module_Target "Python3::Module")
endif()

swig_add_library(yarp_python
  LANGUAGE python
  SOURCES ${SWIG_BINDINGS_SOURCE_FILE}
)
swig_link_libraries(yarp_python ${YARP_Python_Module_Target} ${SWIG_YARP_LIBRARIES})

set_target_properties(${SWIG_MODULE_yarp_python_REAL_NAME}
  PROPERTIES
    OUTPUT_NAME "_yarp"
    LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/python3"
    # treat Python3_INCLUDE_DIRS as non-system so that it can be overriden
    NO_SYSTEM_FROM_IMPORTED TRUE
    SWIG_DEPENDS "${SWIG_YARP_LIBRARIES}"
)

# INCLUDE_DIRECTORIES might have gotten polluted by 3rd-party deps, make sure
# the Python3 header path has more predecence by overriding the previous value
# (set by `swig_link_libraries`) and prepending it to the search path
target_include_directories(${SWIG_MODULE_yarp_python_REAL_NAME} BEFORE PRIVATE ${Python3_INCLUDE_DIRS})

# installation path is determined reliably on most platforms using sysconfig
if(Python3_VERSION VERSION_GREATER_EQUAL 3.12)
  execute_process(COMMAND ${Python3_EXECUTABLE} -c "import os;import sysconfig;relative_site_packages = sysconfig.get_path('purelib').replace(sysconfig.get_path('data'), '').lstrip(os.path.sep);print(relative_site_packages)"
    OUTPUT_VARIABLE Python3_INSTDIR
    OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
  execute_process(COMMAND ${Python3_EXECUTABLE} -c "from distutils import sysconfig; print(sysconfig.get_python_lib(1,0,prefix=''))"
    OUTPUT_VARIABLE Python3_INSTDIR
    OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()

set(_CMAKE_INSTALL_PYTHON3DIR "${Python3_INSTDIR}")
set(CMAKE_INSTALL_PYTHON3DIR ${_CMAKE_INSTALL_PYTHON3DIR} CACHE PATH "python3 bindings (${_CMAKE_INSTALL_PYTHON3DIR})")
mark_as_advanced(CMAKE_INSTALL_PYTHON3DIR)
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_PYTHON3DIR})
  set(CMAKE_INSTALL_FULL_PYTHON3DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_PYTHON3DIR}")
else()
  set(CMAKE_INSTALL_FULL_PYTHON3DIR "${CMAKE_INSTALL_PYTHON3DIR}")
endif()

install(FILES ${CMAKE_BINARY_DIR}/lib/python3/yarp.py
        DESTINATION ${CMAKE_INSTALL_PYTHON3DIR})


# Update RPATH
if(NOT CMAKE_SKIP_RPATH AND NOT CMAKE_SKIP_INSTALL_RPATH)
  file(RELATIVE_PATH _rel_path "${CMAKE_INSTALL_FULL_PYTHON3DIR}" "${CMAKE_INSTALL_FULL_LIBDIR}")
  get_target_property(_current_rpath ${SWIG_MODULE_yarp_python_REAL_NAME} INSTALL_RPATH)
  if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    list(APPEND _current_rpath "@loader_path/${_rel_path}")
  else()
    list(APPEND _current_rpath "\$ORIGIN/${_rel_path}")
  endif()
  set_target_properties(${SWIG_MODULE_yarp_python_REAL_NAME} PROPERTIES INSTALL_RPATH "${_current_rpath}")
endif()

install(
  TARGETS ${SWIG_MODULE_yarp_python_REAL_NAME}
  DESTINATION ${CMAKE_INSTALL_PYTHON3DIR}
)

# Install pip metadata files to ensure that CMake installations of YARP are listed by pip list
# See https://packaging.python.org/specifications/recording-installed-packages/
# and https://packaging.python.org/en/latest/specifications/core-metadata/#core-metadata
option(YARP_PYTHON_PIP_METADATA_INSTALL "Use CMake to install Python pip metadata. Set to false if some other tool installs it." TRUE)
mark_as_advanced(YARP_PYTHON_PIP_METADATA_INSTALL)
set(YARP_PYTHON_PIP_METADATA_INSTALLER "cmake" CACHE STRING "Specify the string to identify the pip Installer. Default: cmake, change this if you are using another tool.")
mark_as_advanced(YARP_PYTHON_PIP_METADATA_INSTALLER)
if(YARP_PYTHON_PIP_METADATA_INSTALL)
  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/METADATA "")
  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/METADATA "Metadata-Version: 2.1\n")
  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/METADATA "Name: yarp\n")
  file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/METADATA "Version: ${YARP_VERSION_SHORT}\n")
  file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/INSTALLER "${YARP_PYTHON_PIP_METADATA_INSTALLER}\n")
  install(
    FILES "${CMAKE_CURRENT_BINARY_DIR}/METADATA" "${CMAKE_CURRENT_BINARY_DIR}/INSTALLER"
    DESTINATION ${CMAKE_INSTALL_PYTHON3DIR}/yarp-${YARP_VERSION_SHORT}.dist-info)
endif()

# We generate some preable for the yarp.py library so that the dll are correctly loaded on Windows
set(swig_python_windows_preable_file ${CMAKE_CURRENT_BINARY_DIR}/swig_python_windows_preable.i)
file(WRITE ${swig_python_windows_preable_file} "")
# If we are on Windows and BUILD_SHARED_LIBS is ON, handle the fact that
# the Python interpreter does not look into PATH to find dll (see https://docs.python.org/3.8/library/os.html#os.add_dll_directory)
if(WIN32 AND BUILD_SHARED_LIBS)
  if(IS_ABSOLUTE ${CMAKE_INSTALL_PYTHON3DIR})
      set(PYTHON_FULL_INSTDIR "${CMAKE_INSTALL_PYTHON3DIR}")
  else()
      set(PYTHON_FULL_INSTDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_PYTHON3DIR}")
  endif()
  file(RELATIVE_PATH RELATIVE_PATH_BETWEEN_INIT_PY_AND_DLL_DIRECTORY ${PYTHON_FULL_INSTDIR} ${CMAKE_INSTALL_FULL_BINDIR})
  file(APPEND ${swig_python_windows_preable_file} "%pythonbegin %{\n")
  file(APPEND ${swig_python_windows_preable_file} "import os\n")
  file(APPEND ${swig_python_windows_preable_file} "library_dll_path = os.path.join(os.path.dirname(__file__),'${RELATIVE_PATH_BETWEEN_INIT_PY_AND_DLL_DIRECTORY}')\n")
  file(APPEND ${swig_python_windows_preable_file} "# Avoid to call add_dll_directory if not necessary,\n")
  file(APPEND ${swig_python_windows_preable_file} "# for example if the library to find are already found in the proper location in a conda environment\n")
  file(APPEND ${swig_python_windows_preable_file} "if(library_dll_path != os.path.join(os.environ.get('CONDA_PREFIX', ''),'Library','bin') and library_dll_path != os.path.join(os.environ.get('CONDA_PREFIX', ''),'bin')):\n")
  file(APPEND ${swig_python_windows_preable_file} "    if(os.path.exists(library_dll_path)):\n")
  file(APPEND ${swig_python_windows_preable_file} "        os.add_dll_directory(library_dll_path)\n")
  file(APPEND ${swig_python_windows_preable_file} "%}\n")
endif()
# Make sure that the created file can be found by swig while parsing the main .i file
set_property(TARGET ${SWIG_MODULE_yarp_python_REAL_NAME} APPEND PROPERTY SWIG_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR})


if(YARP_COMPILE_TESTS)
  add_subdirectory(tests)
endif()

yarp_deprecated_option(CREATE_PYTHON_VERSION)
yarp_deprecated_option(YARP_USE_PYTHON_VERSION)
