cmake_minimum_required(VERSION 3.20.3)

project(lidarview-superbuild)

# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to 'Release' as none was specified.")
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()

list(INSERT CMAKE_MODULE_PATH 0
  "${CMAKE_CURRENT_LIST_DIR}/pvsb/cmake")

# Set LV_BUILD_PLATFORM
set(LV_DISTRO "${CMAKE_SYSTEM_NAME}")
if(UNIX AND NOT APPLE)
  # Use Distro Name+Version instead of plain "Linux"
  find_program(LSB_RELEASE_EXEC lsb_release)
  if(NOT LSB_RELEASE_EXEC)
    message(WARNING "Could not detect lsb_release executable")
  else()
    execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
    execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE_VERSION_SHORT OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(LV_DISTRO "${LSB_RELEASE_ID_SHORT}${LSB_RELEASE_VERSION_SHORT}")
  endif()
endif()
set (LV_BUILD_PLATFORM "${LV_DISTRO}-${CMAKE_SYSTEM_PROCESSOR}")

macro (superbuild_setup_variables)
  include(SuperbuildVersionMacros)

  # Determine paraview version
  if (paraview_SOURCE_SELECTION STREQUAL "git")
    # Assuming master; just use the latest version, but let the user set their
    # own version in case it is actually a branch from some other version.
    set(PARAVIEW_VERSION_DEFAULT "5.11.0"
      CACHE STRING "The default version of ParaView to use if it cannot be detected")
    mark_as_advanced(PARAVIEW_VERSION_DEFAULT)
    set(paraview_default_version "${PARAVIEW_VERSION_DEFAULT}")
  elseif (paraview_SOURCE_SELECTION STREQUAL "source")
    # If it is a git repo, we'll get it that way, otherwise we will look at the
    # `version.txt` in the checkout.
    set(paraview_default_version "")
  else ()
    # The selection is the version number; use it.
    set(paraview_default_version "${paraview_SOURCE_SELECTION}")
  endif()
  superbuild_set_version_variables(paraview "${paraview_default_version}" "paraview-version.cmake" "version.txt")
  set(paraview_version "${paraview_version_major}.${paraview_version_minor}")

  # Determine lidarview (or lidarview based-app) version
  if (lidarview_SOURCE_SELECTION STREQUAL "git")
    # Assuming master; just use the latest version, but let the user set their
    # own version in case it is actually a branch from some other version.
    set(LIDARVIEW_VERSION_DEFAULT "4.5.0"
      CACHE STRING "The default version of LidarView to use if it cannot be detected")
    mark_as_advanced(LIDARVIEW_VERSION_DEFAULT)
    set(lidarview_default_version "${LIDARVIEW_VERSION_DEFAULT}")
  elseif (lidarview_SOURCE_SELECTION STREQUAL "source")
    # If it is a git repo, we'll get it that way, otherwise we will look at the
    # `version.txt` in the checkout.
    set(lidarview_default_version "")
  else ()
    # The selection is the version number; use it.
    set(lidarview_default_version "${lidarview_SOURCE_SELECTION}")
  endif()
  superbuild_set_version_variables(lidarview "${lidarview_default_version}" "lidarview-version.cmake" "version.txt")
  set(lidarview_version "${lidarview_version_major}.${lidarview_version_minor}")
endmacro ()

#------------------------------------------------------------------------------
#SuperBuild Macros

function (superbuild_find_projects var)
  include(ParaViewSuperbuildMacros)

  # Some of these allow using system libraries.
  set(projects
    boost
    bzip2
    ceres
    curl
    cxx11
    darknet
    eigen
    flann
    fortran
    freetype
    g2o
    gdal
    geotiff
    glog
    gtsam
    hesaisdk
    jsonc
    jsoncpp
    lapack
    lidarview
    nanoflann
    nlohmannjson
    numpy
    opencv
    openxrsdk
    paraview
    paraviewweb
    paraviewwebdivvy
    paraviewwebglance
    paraviewweblite
    paraviewwebvisualizer
    pcap
    pcl
    pdal
    png
    proj
    python3
    pythonaiohttp
    pythonasynctimeout
    pythonattrs
    pythonbeniget
    pythonchardet
    pythoncython
    pythongast
    pythonidna
    pythonmultidict
    pythonply
    pythonpythran
    pythonqt
    pythonsetuptools
    pythontypingextensions
    pythonwslinkasync
    pythonyarl
    qhull
    qt5
    slam
    sqlite
    tiff
    xerces
    xz
    yaml
    zlib
    zstd
  )

  if (WIN32)
    list(APPEND projects
      openvr
      pywin32)
  endif()

  if (UNIX)
    list(APPEND projects
      ffi
      libxml2
      sqlite)

    if (NOT APPLE)
      list(APPEND projects
        fontconfig
        gperf
        pkgconf
        teaserpp
        utillinux)
    endif()
  endif()

  # Add lidarview-based app project from old build system
  # with superbuild as a submodule.
  # Should be deprecated for open source projects.
  if (COMMAND add_project_to_superbuild)
    add_project_to_superbuild(projects)
  endif()

  set("${var}"
    ${projects}
    PARENT_SCOPE)
endfunction ()

function (superbuild_sanity_check)
  #TODO
endfunction ()

function (superbuild_add_packaging)

  # Qt logic from pvsb
  if (qt5_enabled AND (USE_SYSTEM_qt5 OR APPLE OR WIN32))
    list(APPEND superbuild_export_variables
      Qt5_DIR)
    find_package(Qt5 QUIET REQUIRED COMPONENTS Core)
    set(qt5_version "${Qt5Core_VERSION_MAJOR}.${Qt5Core_VERSION_MINOR}")
  else ()
    set(qt5_version "${qt5_SOURCE_SELECTION}")
  endif ()
  list(APPEND superbuild_export_variables
    qt5_version)

  # ParaView shared libs logic from pvsb
  if (BUILD_SHARED_LIBS_paraview STREQUAL "<same>")
    set(paraview_is_shared "${BUILD_SHARED_LIBS}")
  else ()
    set(paraview_is_shared "${BUILD_SHARED_LIBS_paraview}")
  endif ()

  # pass some variables that are required for packaging step:
  list(APPEND superbuild_export_variables
    paraview_version
    paraview_is_shared)

  # Packaging tests
  if (WIN32)
    set(generators
      ZIP
      WIX)
  elseif (APPLE)
    set(generators
      DragNDrop)
  else ()
    set(generators
      TGZ)
  endif ()
  list(GET generators 0 default_generator)
  foreach (generator IN LISTS generators)
      superbuild_add_extra_package_test(lidarview "${generator}"
      LABELS  "LidarView" # does not have to be ${SOFTWARE_NAME} I think, it is currently not available here
      TIMEOUT 6400)
  endforeach ()

endfunction ()

function (superbuild_add_tests)
  add_subdirectory("${CMAKE_SOURCE_DIR}/tests" "${CMAKE_BINARY_DIR}/tests")
endfunction ()

# Dependencies Options
option(ENABLE_all "Enable all optional dependencies like pcl, ceres, opencv, ..." OFF)
if (ENABLE_all)
  set(ENABLE_opencv ON CACHE BOOL "enable OpenCV")
  set(ENABLE_ceres ON CACHE BOOL "enable Ceres")
  set(ENABLE_pcl ON CACHE BOOL "enable PCL")
  set(ENABLE_nanoflann ON CACHE BOOL "enable nanoflann")
  # set(ENABLE_darknet ON CACHE BOOL "enable darknet")
  set(ENABLE_g2o ON CACHE BOOL "enable G2O")
  set(ENABLE_gtsam ON CACHE BOOL "enable Gtsam")
  set(ENABLE_teaserpp ON CACHE BOOL "enable Teaser++")
endif(ENABLE_all)

# Qt logic from pvsb
# Differences:
#   - add qtspeech
set(qt5_skip_modules
  qtspeech
  qtconnectivity
  qtgamepad
  qtlocation
  qtsensors
  qtserialport
  qtwayland
  qtwebchannel
  qtwebengine
  qtwebsockets)
set(_superbuild_qt5_default_selection "5.15")
set(qt5_ENABLE_SVG ON CACHE INTERNAL "ParaView requires SVG support") # Localisation lib only required for qtwebkit

# Config Boost
set(boost_libraries
  atomic
  date_time
  filesystem
  iostreams
  program_options
  thread
  timer
  chrono
  regex
  serialization
  system)
set(boost_extra_options
  "-sNO_BZIP2=1")

# Check if some Boost environment variables could hide local Boost install
if (NOT USE_SYSTEM_boost AND (DEFINED ENV{BOOSTROOT} OR DEFINED ENV{BOOST_ROOT} OR DEFINED ENV{BOOST_LIBRARYDIR} OR DEFINED ENV{BOOST_INCLUDEDIR}))
  message(WARNING "Some Boost environment variables are set and may hide the local superbuild Boost installation. "
                  "Consider enabling USE_SYSTEM_boost flag or unsetting the following environement variables :\n"
                  " BOOSTROOT=$ENV{BOOSTROOT}\n BOOST_ROOT=$ENV{BOOST_ROOT}\n BOOST_LIBRARYDIR=$ENV{BOOST_LIBRARYDIR}\n BOOST_INCLUDEDIR=$ENV{BOOST_INCLUDEDIR}")
endif()

# Versions and projects
list(APPEND superbuild_version_files
  "${CMAKE_CURRENT_LIST_DIR}/versions.cmake"
  "${CMAKE_CURRENT_LIST_DIR}/pvsb/versions.cmake")
list(APPEND superbuild_ctest_custom_files
  "${CMAKE_CURRENT_LIST_DIR}/pvsb/cmake/CTestCustom.cmake")
list(APPEND superbuild_project_roots
  "${CMAKE_CURRENT_LIST_DIR}/projects"
  "${CMAKE_CURRENT_LIST_DIR}/pvsb/projects")

# set the default arguments used for "git clone"
set(_git_clone_arguments_default --progress)

# set the default projects
set(_superbuild_default_cxx11 ON)
set(_superbuild_default_lidarview ON)

# set the default for qt5 to be 5.15
set(_superbuild_qt5_default_selection "5.15")

# Force qt SVG support, so ParaView can use SVG icons
set(qt5_ENABLE_SVG ON CACHE INTERNAL "ParaView requires SVG support")

# Force build shared libs
set(_superbuild_no_static_everywhere ON)
set(BUILD_SHARED_LIBS ON)

# Set fixed paraview version on PDAL fix commit until new release come out
set(paraview_GIT_TAG "b5bd6d8beff4d9acdce5b44e0da951710809e4ca" CACHE STRING "")
mark_as_advanced(paraview_GIT_TAG)

# Set ParaView arguments
set(PARAVIEW_EXTERNAL_PROJECTS "pythonqt" CACHE INTERNAL "")
set(PARAVIEW_EXTRA_CMAKE_ARGUMENTS
  "-DVTK_MODULE_ENABLE_VTK_libproj=YES"
  "-DVTK_MODULE_ENABLE_VTK_InteractionImage=YES"  # For PCL
  "-DVTK_MODULE_ENABLE_VTK_RenderingLOD=YES"      # For PCL
  "-DPARAVIEW_PLUGIN_ENABLE_PythonQtPlugin=ON"
  "-DPARAVIEW_PLUGIN_AUTOLOAD_PythonQtPlugin=ON"
  CACHE INTERNAL "")

# common-superbuild
add_subdirectory(pvsb/superbuild)
