cmake_minimum_required(VERSION 3.5)
project(spark)
include(GNUInstallDirs)
include(${CMAKE_SOURCE_DIR}/cmake/safe_dep_glob.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/ProtobufGenerateCpp.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/ProtobufGenerateCppConfig.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/ProtobufGenerateCppService.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateConfigProfile.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/InstallBasic.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/PrintList.cmake)

configure_file(
  "${CMAKE_SOURCE_DIR}/cmake/version.h.in"
  "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/version.h"
)

if(WIN32)
  if(BUILD_SPARKD)
    message(FATAL_ERROR "Cannot build sparkd on Windows (Please set BUILD_SPARKD to False)")
  endif()

  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetWindowsClientSources.cmake)
  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetWindowsClientLinkLibraries.cmake)
elseif(${BUILD_SPARKD})
  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxServerSources.cmake)
  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxServerLinkLibraries.cmake)
else()
  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxClientSources.cmake)
  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxClientLinkLibraries.cmake)
endif()

get_proto_sources(
  ${PROJECT_NAME}_PROTO_CONFIGS
  ${PROJECT_NAME}_PROTO_SOURCES
  ${PROJECT_NAME}_PROTO_SERVICES
)
get_cpp_sources(${PROJECT_NAME}_SOURCES ${PROJECT_NAME}_TEST_SOURCES)
protobuf_generate_cpp(
  CXX_SOURCES ${PROJECT_NAME}_CXX_PROTO_SOURCES
  CXX_HEADERS ${PROJECT_NAME}_CXX_PROTO_HEADERS
  CXX_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}
  PROTO_INCLUDE_DIRS
    ${EXTERNALS_INCLUDE}
    ${CMAKE_CURRENT_SOURCE_DIR}
  PROTO_SOURCES
    ${${PROJECT_NAME}_PROTO_SOURCES}
)

protobuf_generate_cpp_service(
  CXX_SOURCES ${PROJECT_NAME}_CXX_PROTO_SERVICE_SOURCES
  CXX_HEADERS ${PROJECT_NAME}_CXX_PROTO_SERVICE_HEADERS
  CXX_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}
  PROTO_INCLUDE_DIRS
    ${EXTERNALS_INCLUDE}
    ${CMAKE_CURRENT_SOURCE_DIR}
  PROTO_SOURCES
    ${${PROJECT_NAME}_PROTO_SERVICES}
)

# Generate headers for config protos. One header provides the list of proto files in an array to be
# read at runtime in order to generate the aggregated config message type. The other header provides
# an array of strings whose items are lines representing the defaults for this aggregated config
# message type.
set(${PROJECT_NAME}_PROTO_DEFAULTS)
foreach(cfg_path ${CONFIG_DEFAULTS_PATH})
  file(
    GLOB_RECURSE cfg_files
    RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
    ${cfg_path})
  list(APPEND ${PROJECT_NAME}_PROTO_DEFAULTS ${cfg_files})
endforeach()
protobuf_generate_cpp_config(
  PROTO_SOURCES
    ${${PROJECT_NAME}_PROTO_CONFIGS}
  PROTO_SOURCES_HEADER
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/protobufs/config_proto_files.h
  PROTO_DEFAULTS
    ${${PROJECT_NAME}_PROTO_DEFAULTS}
  PROTO_DEFAULTS_HEADER
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/protobufs/config_defaults.h
)

add_library(
  ${PROJECT_NAME}
  SHARED
  ${${PROJECT_NAME}_SOURCES}
  ${${PROJECT_NAME}_CXX_PROTO_SOURCES}
  ${${PROJECT_NAME}_CXX_PROTO_SERVICE_SOURCES}
)

if (WIN32)
  set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "lib")
endif()

target_include_directories(
  ${PROJECT_NAME} PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
  $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

get_link_libraries(_link_libs)
print_list(_link_libs VERBOSE)
target_link_directories(
  ${PROJECT_NAME} PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
  $<INSTALL_INTERFACE:${CMAKE_INSTALL_LIBDIR}>
)
target_link_libraries(${PROJECT_NAME} ${_link_libs})

install(TARGETS ${PROJECT_NAME} DESTINATION "${CMAKE_INSTALL_BINDIR}")

foreach(_hdr ${${PROJECT_NAME}_CXX_PROTO_HEADERS})
  file(RELATIVE_PATH _relative_path ${CMAKE_CURRENT_BINARY_DIR} ${_hdr})
  install(FILES ${_hdr} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${_relative_path})
endforeach()

foreach(_hdr ${${PROJECT_NAME}_CXX_PROTO_SERVICE_HEADERS})
  file(RELATIVE_PATH _relative_path ${CMAKE_CURRENT_BINARY_DIR} ${_hdr})
  install(FILES ${_hdr} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${_relative_path})
endforeach()

install_basic()

# Add tests executable (if there are any)
if (${PROJECT_NAME}_TEST_SOURCES AND NOT WIN32)
  add_executable(${PROJECT_NAME}-tests ${${PROJECT_NAME}_TEST_SOURCES})

  # Set RPATH so the tests exe knows where to find the shared lib.
  set_target_properties(
    ${PROJECT_NAME}-tests
    PROPERTIES
      BUILD_RPATH "$ORIGIN"
      INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}"
  )

  # Link main lib
  target_link_directories(
    ${PROJECT_NAME}-tests
    PRIVATE
      $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
      $<INSTALL_INTERFACE:${CMAKE_INSTALL_LIBDIR}>
  )
  target_link_libraries(${PROJECT_NAME}-tests PRIVATE ${PROJECT_NAME})

  # Catch2
  find_package(Catch2 CONFIG REQUIRED COMPONENTS Catch2WithMain)
  target_link_libraries(${PROJECT_NAME}-tests PRIVATE Catch2::Catch2WithMain)
endif()
