#include <utils/BuildInfo.hpp>
#include <utils/Stringify.hpp>
#include <utils/pugs_build_info.hpp>
#include <utils/pugs_config.hpp>

#include <sstream>

#ifdef PUGS_HAS_MPI
#include <mpi.h>
#endif   //  PUGS_HAS_MPI

#ifdef PUGS_HAS_PETSC
#include <petsc.h>
#endif   // PUGS_HAS_PETSC

#ifdef PUGS_HAS_SLEPC
#include <slepc.h>
#endif   // PUGS_HAS_PETSC

#ifdef PUGS_HAS_HDF5
#include <highfive/highfive.hpp>
#endif   // PUGS_HAS_HDF5

#ifdef PUGS_HAS_SLURM
#include <slurm/slurm.h>
#endif   // PUGS_HAS_SLURM

std::string
BuildInfo::type()
{
  return PUGS_BUILD_TYPE;
}

std::string
BuildInfo::compiler()
{
  std::stringstream compiler_info;
  compiler_info << PUGS_BUILD_COMPILER << " (" << PUGS_BUILD_COMPILER_VERSION << ")";
  return compiler_info.str();
}

std::string
BuildInfo::kokkosDevices()
{
  return PUGS_BUILD_KOKKOS_DEVICES;
}

std::string
BuildInfo::mpiLibrary()
{
#ifdef PUGS_HAS_MPI
  return []() {
    int length;
    char mpi_version[MPI_MAX_LIBRARY_VERSION_STRING];
    MPI_Get_library_version(mpi_version, &length);
    return std::string(mpi_version);
  }();
#else    // PUGS_HAS_MPI
  return "none";
#endif   // PUGS_HAS_MPI
}

std::string
BuildInfo::petscLibrary()
{
#ifdef PUGS_HAS_PETSC
  return stringify(PETSC_VERSION_MAJOR) + "." + stringify(PETSC_VERSION_MINOR) + "." +
         stringify(PETSC_VERSION_SUBMINOR);
#else    // PUGS_HAS_PETSC
  return "none";
#endif   // PUGS_HAS_PETSC
}

std::string
BuildInfo::slepcLibrary()
{
#ifdef PUGS_HAS_SLEPC
  return stringify(SLEPC_VERSION_MAJOR) + "." + stringify(SLEPC_VERSION_MINOR) + "." +
         stringify(SLEPC_VERSION_SUBMINOR);
#else    // PUGS_HAS_SLEPC
  return "none";
#endif   // PUGS_HAS_SLEPC
}

std::string
BuildInfo::hdf5Library()
{
#ifdef PUGS_HAS_HDF5

#ifdef H5_HAVE_PARALLEL
  return stringify(H5_VERSION) + " [parallel]";
#else    // H5_HAVE_PARALLEL
  return stringify(H5_VERSION) + " [sequential]";
#endif   // H5_HAVE_PARALLEL

#else    // PUGS_HAS_HDF5
  return "none";
#endif   // PUGS_HAS_HDF5
}

std::string
BuildInfo::slurmLibrary()
{
#ifdef PUGS_HAS_SLURM

  return stringify(SLURM_VERSION_MAJOR(SLURM_VERSION_NUMBER)) + "." +
         stringify(SLURM_VERSION_MINOR(SLURM_VERSION_NUMBER)) + "." +
         stringify(SLURM_VERSION_MICRO(SLURM_VERSION_NUMBER));

#else    // PUGS_HAS_SLURM
  return "none";
#endif   // PUGS_HAS_SLURM
}