# Define the minimum cmake version required
cmake_minimum_required(VERSION "3.10.2" FATAL_ERROR)

include(CMakeDependentOption)

set(CMAKE_CONFIGURATION_TYPES Debug;Release CACHE STRING "" FORCE)

# Modules examples
Project(AllModulesExamples)

#Be sure all demos require C++ 17 Standard
if (NOT APPLE)
  set(CMAKE_CXX_STANDARD 17)

  # Do not propagate C++ 17 option to Cuda Examples
  if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
    SET(CUDA_PROPAGATE_HOST_FLAGS OFF)
  endif()
endif()

# when building internally, this file exists and we can use our conan Qt prepack
# when the client builds, this file will not be packaged, and this they will need to givbe the paths to Qt
if(NOT OIV_DEV_BUILD AND NOT OIV_DEMOS_SKIP_CONAN AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/oivDemosInternalConanfile.txt)
  # Fetch needed conan prepacked packages
  include(${CMAKE_CURRENT_SOURCE_DIR}/../source/cmake/conan.cmake)
  SET_CONAN_INCLUDE(${CMAKE_CURRENT_SOURCE_DIR}/../source/cmake)

  # On test machines, cmake is invoked with -DCMAKE_BUILD_TYPE=Release or -DCMAKE_BUILD_TYPE=Debug option.
  # This causes conan to use cmake generator instead of cmake-multi generator.
  # To avoid problems, we temporary delete the CMAKE_BUILD_TYPE variable and recreate it after conan invocation.
  if(WIN32 AND CMAKE_BUILD_TYPE)
    set(OLD_CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
    unset(CMAKE_BUILD_TYPE CACHE)
  endif()

  # this is ugly, but on mac os we have a different version of Qt, thus we need either
  # a different conanfile.txt or a conanfile.py
  # it seems simpler to have a different conanfile.txt
  # this can be removed when we update Qt on MacOS (which requires upgrading the MacOS toolchain)
  set(CONANFILE oivDemosInternalConanfile.txt)
  if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.30)
      set(CONANFILE oivDemosInternalConanfile_qt6.txt)
    endif()
  endif()

  conan_cmake_run(CONANFILE ${CONANFILE}
                  BASIC_SETUP
                  UPDATE
                  BUILD never)

  if(OLD_CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE ${OLD_CMAKE_BUILD_TYPE} CACHE STRING "Build type")
    unset(OLD_CMAKE_BUILD_TYPE)
  endif()
endif()

# Hack to get other generators working on windows. Should not be necessary as soon as the copyprepackeddll.cmake file is not used anymore.
if(MSVC_IDE)
  set(OIV_BUILD_TYPE ${CMAKE_CFG_INTDIR})
else()
  set(OIV_BUILD_TYPE ${CMAKE_BUILD_TYPE})
endif()

# Hide (and set to FALSE) OIV_LOCAL_PROJECT option in OIV_DEV_BUILD mode
cmake_dependent_option(OIV_LOCAL_PROJECT "genarate local project ready to distrib" TRUE "NOT OIV_DEV_BUILD" FALSE)

if (OIV_LOCAL_PROJECT)
  set(CMAKE_SUPPRESS_REGENERATION TRUE)
  set(CMAKE_USE_RELATIVE_PATH TRUE)
else()
  if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
    message(FATAL_ERROR "CMake generation is not allowed within the
        source directory! Remove the CMakeCache.txt file and try again from another folder, e.g.:

        rm CMakeCache.txt
        mkdir -p build/{debug/release}
        cd build/debug
        cmake  ../..
      ")
  endif()
endif()

set(OIV_ENABLE_EBUGS FALSE)

message(STATUS "${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_SOURCE_DIR}")

# False by default as we only want to activate this on freeze branch
option(OIV_WARNING_AS_ERROR "Force warning in code to be considered as error" FALSE)

# Assume that all modules are available. Default values can be changed below.
option(OIV_ENABLE_INVENTOR_EXAMPLES "Enable Inventor examples" TRUE)
option(OIV_ENABLE_DIALOGVIZ_EXAMPLES "Enable DialogViz examples" TRUE)
option(OIV_ENABLE_HARDCOPY_EXAMPLES "Enable HardCopy examples" TRUE)
option(OIV_ENABLE_MESHVIZ_EXAMPLES "Enable MeshViz examples" TRUE)
option(OIV_ENABLE_MESHVIZXLM_EXAMPLES "Enable MeshVizXLM examples" TRUE)
option(OIV_ENABLE_VOLUMEVIZ_EXAMPLES "Enable VolumeViz examples" TRUE)
option(OIV_ENABLE_MEDICAL_EXAMPLES "Enable Medical examples" TRUE)
option(OIV_ENABLE_REMOTEVIZ_SERVICES_EXAMPLES "Enable RemoteViz services examples" TRUE)
option(OIV_ENABLE_REMOTEVIZ_CLIENT_EXAMPLES "Enable RemoteViz Client examples" TRUE)

# lots of demos require this to compile properly because they use <> instead of "" for includes in the same dir
set(CMAKE_INCLUDE_CURRENT_DIR TRUE)

# Detect if we are running CMake starting from demo directory or from
# main OivSuite directory
if(NOT OIV_DEV_BUILD AND ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})

  # Here we have ran CMake directly in the demo directory
  set(OIV_COMMON_CMAKE_DIR ${CMAKE_SOURCE_DIR}/../source/cmake )
  include( ${OIV_COMMON_CMAKE_DIR}/FindGit.cmake )
  include( ${OIV_COMMON_CMAKE_DIR}/InternalBuildKey.cmake )
  include( ${OIV_COMMON_CMAKE_DIR}/GPUDetection.cmake )

  if(OIV_INTERNAL_BUILD_KEY)
    message(STATUS "SHA1 build key: ${OIV_INTERNAL_BUILD_KEY}")
  endif()

  # ensure we find the OpenInventorConfig.cmake file
  list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_LIST_DIR}/../source/cmake/config)

  find_package(OpenInventor REQUIRED)

  include(${OIV_COMMON_CMAKE_DIR}/UsefulMacros.cmake)
  include(${OIV_COMMON_CMAKE_DIR}/DefaultCompilerFlags.cmake)

  # Enable _SCL_SECURE_NO_WARNINGS to avoid warning C4996 on Windows
  if(MSVC)
    add_definitions(-D_SCL_SECURE_NO_WARNINGS)
  endif()

  if (OIV_WARNING_AS_ERROR)
    #Enable warnings as errors
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
  endif()

  enable_examples(MEDICAL ${fei_inventor_medical_FOUND})
  enable_examples(DIALOGVIZ ${fei_dialogViz_FOUND})
  enable_examples(HARDCOPY ${fei_hardCopy_FOUND})
  enable_examples(MESHVIZ ${fei_meshViz_FOUND})
  enable_examples(MESHVIZXLM ${fei_meshVizXLM_extractor_FOUND})
  enable_examples(VOLUMEVIZ ${fei_volumeViz_FOUND})
  enable_examples(REMOTEVIZ_SERVICES ${fei_remoteViz_services_FOUND})
  enable_examples(REMOTEVIZ_CLIENT ${fei_remoteViz_client_FOUND})
else()
  include(${OIV_COMMON_CMAKE_DIR}/UsefulMacros.cmake)

  enable_examples(DIALOGVIZ ${OIV_ENABLE_DIALOGVIZ})
  enable_examples(HARDCOPY ${OIV_ENABLE_HARDCOPY})
  enable_examples(MESHVIZ ${OIV_ENABLE_MESHVIZ})
  enable_examples(MESHVIZXLM ${OIV_ENABLE_MESHVIZXLM})
  enable_examples(VOLUMEVIZ ${OIV_ENABLE_VOLUMEVIZ})
  enable_examples(REMOTEVIZ_SERVICES ${OIV_ENABLE_REMOTEVIZ_SERVICES})
  enable_examples(REMOTEVIZ_CLIENT ${OIV_ENABLE_REMOTEVIZ_CLIENT})
endif()

# Detect X11 (then if(X11_FOUND) can be used)
if(NOT OIV_ENABLE_HEADLESS AND UNIX AND NOT APPLE)
  find_package(Motif REQUIRED)
  find_package(X11 REQUIRED)
endif()

if (OIV_ENABLE_HEADLESS)
  # Disable all examples except RemoteViz Service Examples when using headless mode
  enable_examples(INVENTOR FALSE)
  enable_examples(MEDICAL FALSE)
  enable_examples(DIALOGVIZ FALSE)
  enable_examples(HARDCOPY FALSE)
  enable_examples(MESHVIZ FALSE)
  enable_examples(MESHVIZXLM FALSE)
  enable_examples(VOLUMEVIZ FALSE)
  enable_examples(REMOTEVIZ_SERVICES ${fei_remoteViz_services_FOUND})
  enable_examples(REMOTEVIZ_CLIENT FALSE)
endif()

include( ${OIV_COMMON_CMAKE_DIR}/CMakePolicy.cmake NO_POLICY_SCOPE )
include( ${OIV_COMMON_CMAKE_DIR}/SystemDetection.cmake )

# ###################################################
# Experimental option to force all demos to build with Qt
cmake_dependent_option( OIV_DEMOS_QT_ONLY "Use Qt viewers for all demos." FALSE "NOT OIV_ENABLE_HEADLESS" FALSE )

# ###################################################
# Option to enable/disable all demos using Qt
cmake_dependent_option( OIV_ENABLE_QT_DEMOS "Enable all demos using Qt." TRUE "NOT OIV_ENABLE_HEADLESS" FALSE )
if(OIV_ENABLE_QT_DEMOS)
  set(TARGETED_QT_VERSION Qt5)
  if(NOT OIV_FORCE_QT5 AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
    if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.30)
      set(TARGETED_QT_VERSION Qt6)
    endif()
  endif()

  if(CONAN_LIB_DIRS_QT)
    list(GET CONAN_LIB_DIRS_QT 0 LIB_PATH)
  elseif(CONAN_LIB_DIRS_QT_RELEASE)
    list(GET CONAN_LIB_DIRS_QT_RELEASE 0 LIB_PATH)
  elseif(CONAN_LIB_DIRS_QTCOMMERCIAL)
      list(GET CONAN_LIB_DIRS_QTCOMMERCIAL 0 LIB_PATH)
  elseif(CONAN_LIB_DIRS_QTCOMMERCIAL_RELEASE)
    list(GET CONAN_LIB_DIRS_QTCOMMERCIAL_RELEASE 0 LIB_PATH)
  endif()
  list(APPEND CMAKE_PREFIX_PATH "${LIB_PATH}/cmake/${TARGETED_QT_VERSION}")
  find_package(QT NAMES ${TARGETED_QT_VERSION} COMPONENTS Core QUIET)
  if(NOT QT_VERSION_MAJOR)
    set(QT_VERSION_MAJOR 5)
    if(TARGETED_QT_VERSION STREQUAL Qt6)
      set(QT_VERSION_MAJOR 6)
    endif()
  endif()
endif()

if(WIN32)
  add_definitions(-DQT_DLL)
endif()

if (OIV_DEMOS_QT_ONLY)
  add_definitions(-DSOQT)
  # Find needed Qt Packages
  find_package(QT NAMES ${TARGETED_QT_VERSION} REQUIRED COMPONENTS Core)
  find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui OpenGL PrintSupport Xml Widgets REQUIRED)

  set(_libraries
    Qt::Core
    Qt::Gui
    Qt::OpenGL
    Qt::Widgets
  )

  if ((DEFINED UNIX) AND (${QT_VERSION_MAJOR} EQUAL 5))
    find_package(Qt5 COMPONENTS X11Extras REQUIRED)
    list(APPEND _libraries Qt5::X11Extras)
  endif()

  link_libraries (
    ${_libraries}
  )

  set( OpenInventorWin_LIBRARIES ${OpenInventorQt_LIBRARIES} )
  set( OpenInventorXt_LIBRARIES ${OpenInventorQt_LIBRARIES} )
  set( DialogViz_LIBRARIES ${DialogVizQt_LIBRARIES} )
endif()

# ###############################################
# tests

if (NOT OIV_LOCAL_PROJECT)
  include(${OIV_COMMON_CMAKE_DIR}/OIVTests.cmake)
  # UnitTests that want to explicitly add a RUN_TEST program must use the ADD_OIV_RUNTEST_EXE macro
  option( OIV_ENABLE_RUNTESTS "Enable binaries execution testing" TRUE )
  mark_as_advanced( OIV_ENABLE_RUNTESTS )

  cmake_dependent_option( OIV_ENABLE_ART_TESTS "Enable ART Tests." TRUE "NOT OIV_ENABLE_HEADLESS" FALSE )

  if (NOT HOSTNAME)
    site_name(HOSTNAME)
  endif()
  # Remove dots from hostname
  string(REPLACE "." ";" HOSTNAME_LIST ${HOSTNAME})
  list(GET HOSTNAME_LIST 0 HOSTNAME)

  if(OIV_DEV_BUILD)
    set(OIV_ART_REFERENCES_SUBMOD "${CMAKE_SOURCE_DIR}/TestReferences/${HOSTNAME}/")
  else()
    set(OIV_ART_REFERENCES_SUBMOD "${CMAKE_SOURCE_DIR}/../../TestReferences/${HOSTNAME}/")
  endif()

  get_filename_component(OIV_ART_REFERENCES_SUBMOD "${OIV_ART_REFERENCES_SUBMOD}" ABSOLUTE)

  # The reference path for the tests data
  SET(OIV_TESTS_REFERENCE_PATH "${OIV_ART_REFERENCES_SUBMOD}/OIVHOME/src")

  # set the output path for the ART output only if it was not passed as parameter
  if(NOT OIV_TESTS_OUTPUT_PATH)
    SET(OIV_TESTS_OUTPUT_PATH "${OIV_ART_REFERENCES_SUBMOD}/generated/demos")
  else()
    # when the output path is passed as a parameter, it is a relative path to the build dir
    # adding the build dir as prefix to make sure the proper path is found
    SET(OIV_TESTS_OUTPUT_PATH "${CMAKE_BINARY_DIR}/${OIV_TESTS_OUTPUT_PATH}")
  endif()

  OivTestsInit()
endif()

# ############################################

if ( OIV_LOCAL_PROJECT AND NOT OIV_DEV_BUILD )
  configure_file(${CMAKE_SOURCE_DIR}/../source/cmake/RelativeProjectWindows.cmake.in  ${CMAKE_BINARY_DIR}/cmake/RelativeProjectWindows.cmake @ONLY)
else()
  ADD_ART_TEST()
endif()

# In not OIV_DEV_BUILD, ${CMAKE_SOURCE_DIR} is OIVHOME/examples/source and we have to copy CTestCustom.cmake to build directory
# In OIV_DEV_BUILD, this copyt is done by CMakeList.txt at the root of OivSuite.
if ( NOT OIV_DEV_BUILD )
  configure_file(${CMAKE_SOURCE_DIR}/../source/cmake/CTestCustom.cmake ${CMAKE_BINARY_DIR} @ONLY)
  configure_file(${CMAKE_SOURCE_DIR}/../source/cmake/GPUDetection.cmake ${CMAKE_BINARY_DIR})
  configure_file(${CMAKE_SOURCE_DIR}/../source/cmake/SystemDetection.cmake ${CMAKE_BINARY_DIR})
endif()

include_directories(${OIV_INCLUDE_DIR})

add_subdirectory(source)
