cmake_minimum_required(VERSION 3.5)

# Project name
project(QualisysKinovaInterface)

# Activate C++ 20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# guard against in-source builds
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
  message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
endif()

# guard against bad build-type strings
if (NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_VERBOSE_MAKEFILE      ON)
set(CMAKE_COLOR_MAKEFILE        ON)

# Options for Kortex library
option(USE_CONAN "Use the Conan package manager to automatically fetch the Kortex API" OFF)
option(DOWNLOAD_API "Automatically download the API if conan is not used" ON)

###############
# GTKMM library
###############
find_package(PkgConfig REQUIRED)
pkg_check_modules(gtkmm REQUIRED IMPORTED_TARGET gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})

################
# wxWidgets lib
################
find_package(wxWidgets REQUIRED gl core base OPTIONAL_COMPONENTS net)
include(${wxWidgets_USE_FILE})

################
# Eigen library
################
find_package(Eigen3 3.3 REQUIRED NO_MODULE)

################
# SPDLog library
################
find_package(spdlog REQUIRED)

################
# Kortex library
################
set(KORTEX_SOURCE_DIR "${PROJECT_SOURCE_DIR}/lib/kortex-2.5.0/api_cpp/examples")

macro(configure_msvc_runtime)

    # Default to statically-linked runtime.
    if("${MSVC_RUNTIME}" STREQUAL "")
      set(MSVC_RUNTIME "static")
    endif()

    # Set compiler options.
    set(variables
      CMAKE_C_FLAGS_DEBUG
      CMAKE_C_FLAGS_MINSIZEREL
      CMAKE_C_FLAGS_RELEASE
      CMAKE_C_FLAGS_RELWITHDEBINFO
      CMAKE_CXX_FLAGS_DEBUG
      CMAKE_CXX_FLAGS_MINSIZEREL
      CMAKE_CXX_FLAGS_RELEASE
      CMAKE_CXX_FLAGS_RELWITHDEBINFO
    )
    
    if(${MSVC_RUNTIME} STREQUAL "static")
      message(STATUS
        "MSVC -> forcing use of statically-linked runtime."
      )
      foreach(variable ${variables})
        if(${variable} MATCHES "/MD")
          string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}")
        endif()
      endforeach()
    
    else()
      message(STATUS
        "MSVC -> forcing use of dynamically-linked runtime."
      )
      foreach(variable ${variables})
        if(${variable} MATCHES "/MT")
          string(REGEX REPLACE "/MT" "/MD" ${variable} "${${variable}}")
        endif()
      endforeach()

    endif()

endmacro()

include_directories(${KORTEX_SOURCE_DIR}/thirdParty/cxxopts/)

if(MSVC)
  configure_msvc_runtime()
else()
  add_compile_options(-Wall)
  add_compile_options(-Wno-reorder)
endif()

if(UNIX)
  add_definitions(-D_OS_UNIX)
elseif(WIN32)
  add_definitions(-D_OS_WINDOWS -DNOMINMAX)
  if(MSVC)
     add_compile_options(/bigobj)
  endif()
endif()

if(USE_CONAN)

  include(${KORTEX_SOURCE_DIR}/thirdParty/conan.cmake)

  conan_check(REQUIRED)
  conan_add_remote(
    NAME kinova_public 
    URL https://artifactory.kinovaapps.com/artifactory/api/conan/conan-public)

  if(UNIX)
    conan_cmake_run(REQUIRES kortex_api_cpp/2.3.0-r.34@kortex/stable
                    SETTINGS kortex_api_cpp:compiler=gcc
                    SETTINGS kortex_api_cpp:compiler.version=5
                    SETTINGS compiler.libcxx=libstdc++11
                    PROFILE_AUTO build_type
                    BASIC_SETUP
                    UPDATE)
  elseif(WIN32)
    if(MSVC)

      _get_msvc_ide_version(_VISUAL_VERSION)

      if (_VISUAL_VERSION EQUAL 14)
        set(kortex_api_cpp_target "msvc-2015")
      elseif(_VISUAL_VERSION EQUAL 15)
        set(kortex_api_cpp_target "msvc-2017")
      elseif(_VISUAL_VERSION EQUAL 16)
        set(kortex_api_cpp_target "msvc-2019")
      endif()

      conan_cmake_run(REQUIRES kortex_api_cpp/2.3.0-r.34@kortex/stable
                      PROFILE_AUTO build_type
                      BASIC_SETUP
                      UPDATE)
      
    else()
      conan_cmake_run(REQUIRES kortex_api_cpp/2.3.0-r.34@kortex/stable
                      SETTINGS kortex_api_cpp:compiler=gcc
                      SETTINGS kortex_api_cpp:compiler.version=5
                      SETTINGS compiler.libcxx=libstdc++11
                      PROFILE_AUTO build_type
                      BASIC_SETUP
                      UPDATE)
    endif()
  endif()

  link_libraries(${CONAN_LIBS})

else() # Not using Conan

  # Setup Kortex Api Path
  if(NOT KORTEX_SUB_DIR)
    set(KORTEX_SUB_DIR "")
  else()
    set(KORTEX_SUB_DIR "${KORTEX_SUB_DIR}/")
  endif()

  set(KORTEX_DIR "${KORTEX_SOURCE_DIR}/kortex_api/${KORTEX_SUB_DIR}")

  if(CMAKE_BUILD_TYPE EQUAL "Debug")
    set(KORTEX_LIB_SUBDIR "debug")
  else()
    set(KORTEX_LIB_SUBDIR "release")
  endif()

  # Download the API
  if(DOWNLOAD_API)
    if(UNIX)
      execute_process(COMMAND ./download_kortex_api.sh ${KORTEX_SUB_DIR}
        WORKING_DIRECTORY ${KORTEX_SOURCE_DIR}/scripts
        RESULT_VARIABLE DOWNLOAD_API_RESULT
        OUTPUT_VARIABLE DOWNLOAD_API_OUTPUT)
      if(NOT DOWNLOAD_API_RESULT EQUAL 0)
        message("Kortex API was not downloaded prior to running CMake.")
        message(FATAL_ERROR ${DOWNLOAD_API_OUTPUT})
      endif()
    elseif(WIN32)
      execute_process(COMMAND ./download_kortex_api.bat ${KORTEX_SUB_DIR}
        WORKING_DIRECTORY ${KORTEX_SOURCE_DIR}/scripts
        RESULT_VARIABLE DOWNLOAD_API_RESULT
        OUTPUT_VARIABLE DOWNLOAD_API_OUTPUT)
      if(NOT DOWNLOAD_API_RESULT EQUAL 0)
        message("Kortex API was not downloaded prior to running CMake.")
        message(FATAL_ERROR ${DOWNLOAD_API_OUTPUT})
      endif()
    endif()
  endif()
  if(UNIX)
    link_libraries(${KORTEX_DIR}lib/${KORTEX_LIB_SUBDIR}/libKortexApiCpp.a)
  elseif(WIN32)
    link_libraries(${KORTEX_DIR}lib/${KORTEX_LIB_SUBDIR}/KortexApiCpp.lib)
  endif()

  # Add Include Directories
  include_directories(${KORTEX_DIR}include)
  include_directories(${KORTEX_DIR}include/client)
  include_directories(${KORTEX_DIR}include/common)
  include_directories(${KORTEX_DIR}include/messages)
  include_directories(${KORTEX_DIR}include/client_stubs)
endif()

# link other libs
if(UNIX)
  link_libraries(pthread)
elseif(WIN32)
  link_libraries(winMM ws2_32)
else()
  MESSAGE(FATAL_ERROR "Unknown os! Not supported yet")
endif()

##################
# Qualisys library
##################
# add_subdirectory("${PROJECT_SOURCE_DIR}/lib/qualisys-1.23")
find_package(qualisys_cpp_sdk REQUIRED)

##################
# QuIK library
##################
include_directories("${PROJECT_SOURCE_DIR}/lib/QuIK/C++/QuIK/IK")
include_directories("${PROJECT_SOURCE_DIR}/lib/QuIK/C++/QuIK/Robot")

# Source files
file(GLOB_RECURSE SOURCES "${PROJECT_SOURCE_DIR}/src/*.cpp")

# Executable
add_executable(${PROJECT_NAME} ${SOURCES}) # PkgConfig::gtkmm
target_link_libraries(${PROJECT_NAME} ${wxWidgets_LIBRARIES} Eigen3::Eigen qualisys_cpp_sdk spdlog::spdlog $<$<BOOL:${MINGW}>:ws2_32>)
target_include_directories(${PROJECT_NAME} PRIVATE "${PROJECT_SOURCE_DIR}/include/")