#------------------------------------------------------------------------------#
# Copyright (c) 2024, Triad National Security, LLC.
# All rights reserved.
#------------------------------------------------------------------------------#

cmake_minimum_required(VERSION 3.23)

#------------------------------------------------------------------------------#
# Add local module path.
#------------------------------------------------------------------------------#

list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)

#------------------------------------------------------------------------------#
# CMake policies.
#------------------------------------------------------------------------------#

cmake_policy(SET CMP0144 NEW) # ``PACKAGE_NAME''_ROOT
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.30.0")
  # squelch warning in newer CMake versions
  cmake_policy(SET CMP0167 NEW) # FindBoost
endif()

#------------------------------------------------------------------------------#
# Project
#------------------------------------------------------------------------------#

project(UC_APPNAME LANGUAGES C CXX)

set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)

#------------------------------------------------------------------------------#
# Version
#------------------------------------------------------------------------------#

include(version)

#------------------------------------------------------------------------------#
# Find the FleCSI package. This must be done early so that the FleCSI cmake
# packages will be available to the project, e.g., 'include(FleCSI/unit)'.
#
# CMake documentation for FleCSI client applications is included in the
# FleCSI userguide.
#------------------------------------------------------------------------------#

if(NOT FleCSI_FOUND)
  find_package(FleCSI 2 REQUIRED)
endif()

#------------------------------------------------------------------------------#
# Formatting
#------------------------------------------------------------------------------#

option(ENABLE_FORMAT "Enable format target" OFF)
mark_as_advanced(ENABLE_FORMAT)

if(ENABLE_FORMAT)
  include(FleCSI/format)
 
  set(CLANG_FORMAT_VERSION "18...<19" CACHE STRING
      "Set the required version (major[.minor[.patch]]) of clang-format")
  mark_as_advanced(CLANG_FORMAT_VERSION)
 
  flecsi_add_format_target(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}
    "${CLANG_FORMAT_VERSION}")
endif()

#------------------------------------------------------------------------------#
# Set floating-point precision.
#------------------------------------------------------------------------------#

set(CONFIG_PRECISIONS double float)
if(NOT CONFIG_PRECISION)
  list(GET CONFIG_PRECISIONS 0 CONFIG_PRECISION)
endif()

set(CONFIG_PRECISION "${CONFIG_PRECISION}" CACHE STRING
  "Select the floating-point precision")
set_property(CACHE CONFIG_PRECISION PROPERTY STRINGS ${CONFIG_PRECISIONS})
set(Config_PRECISION "${CONFIG_PRECISION}")

option(ENABLE_SANITY_BUILD "Enable sanity check" OFF)
mark_as_advanced(ENABLE_SANITY_BUILD)

#------------------------------------------------------------------------------#
# UC_APPNAME Library
#------------------------------------------------------------------------------#

if(NOT ENABLE_SANITY_BUILD)

  #----------------------------------------------------------------------------#
  # Build shared libraries by default
  #----------------------------------------------------------------------------#

  option(BUILD_SHARED_LIBS "Build shared libs" ON)
  mark_as_advanced(BUILD_SHARED_LIBS)

  #----------------------------------------------------------------------------#
  # Add library.
  #----------------------------------------------------------------------------#

  set(MODULES_TARGET "${CMAKE_PROJECT_NAME}-Modules")
  add_library(${MODULES_TARGET} INTERFACE)
  add_library(${MODULES_TARGET}::${MODULES_TARGET} ALIAS ${MODULES_TARGET})
  target_include_directories(${MODULES_TARGET}
    INTERFACE
      $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
      $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}>
      $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

  #----------------------------------------------------------------------------#
  # Unit tests.
  # Note: This has to be in the top-level CMakeLists.txt file.
  #----------------------------------------------------------------------------#

  option(ENABLE_UNIT_TESTS "Enable unit testing" OFF)
  mark_as_advanced(ENABLE_UNIT_TESTS)

  include(FleCSI/unit)
  if(ENABLE_UNIT_TESTS)
    flecsi_enable_testing()
  endif()

  #----------------------------------------------------------------------------#
  # Modules library sources.
  #----------------------------------------------------------------------------#

  add_subdirectory(modules)

  #----------------------------------------------------------------------------#
  # Config header.
  #----------------------------------------------------------------------------#

  configure_file(${PROJECT_SOURCE_DIR}/modules/config.hh.in
    ${CMAKE_BINARY_DIR}/modules/config.hh @ONLY)

  #----------------------------------------------------------------------------#
  # Application
  #----------------------------------------------------------------------------#

  add_subdirectory(app)
endif()

#------------------------------------------------------------------------------#
# Output configuration summary.
#------------------------------------------------------------------------------#

include(FleCSI/summary)

flecsi_summary_header()
flecsi_summary_info("UC_APPNAME Version" "${UC_APPNAME_VERSION_BRIEF}" FALSE)

string(APPEND _summary "\n")

if(UC_APPNAME_REPO_STATE)
  flecsi_summary_info("Repository state" "${UC_APPNAME_REPO_STATE}" FALSE)
endif()

string(APPEND _summary "\n")

if(NOT ENABLE_SANITY_BUILD)
  flecsi_summary_info("CMAKE_BUILD_TYPE" "${CMAKE_BUILD_TYPE}" TRUE)
  flecsi_summary_info("CMAKE_INSTALL_PREFIX" "${CMAKE_INSTALL_PREFIX}" TRUE)
  string(APPEND _summary "\n")
  flecsi_summary_info("CMAKE_CXX_COMPILER" "${CMAKE_CXX_COMPILER}" TRUE)
  flecsi_summary_info("CMAKE_CXX_COMPILER_VERSION"
    "${CMAKE_CXX_COMPILER_VERSION}" TRUE)
  flecsi_summary_info("CMAKE_CXX_FLAGS" "${CMAKE_CXX_FLAGS}" TRUE)
  flecsi_summary_info("CMAKE_C_COMPILER" "${CMAKE_C_COMPILER}" TRUE)
  flecsi_summary_info("CMAKE_C_COMPILER_VERSION" "${CMAKE_C_COMPILER_VERSION}" TRUE)
  flecsi_summary_info("CMAKE_C_FLAGS" "${CMAKE_C_FLAGS}" TRUE)

  string(APPEND _summary "\n")
  flecsi_summary_option("ENABLE_UNIT_TESTS" ${ENABLE_UNIT_TESTS} "")
  string(APPEND _summary "\n")
endif()

if(ENABLE_FORMAT AND TARGET ClangFormat::ClangFormat)
  flecsi_summary_info("ClangFormat_EXECUTABLE" "${ClangFormat_EXECUTABLE}" TRUE)
endif()

message(STATUS ${_summary})
