#include <Messenger.hpp>
#include <PastisOStream.hpp>

namespace parallel
{

Messenger* Messenger::m_instance = nullptr;

void Messenger::create(int& argc, char* argv[])
{
  if (Messenger::m_instance == nullptr) {
    Messenger::m_instance = new Messenger(argc, argv);
  } else {
    std::cerr << "Messenger already created\n";
    std::exit(1);
  }
}

void Messenger::destroy()
{
  // One allows multiple destruction to handle unexpected code exit
  if (Messenger::m_instance != nullptr) {
    delete Messenger::m_instance;
    Messenger::m_instance = nullptr;
  }
}

Messenger::
Messenger([[maybe_unused]] int& argc,
          [[maybe_unused]] char* argv[])
{
#ifdef PASTIS_HAS_MPI
  MPI_Init(&argc, &argv);

  m_rank = [] () {
             int rank;
             MPI_Comm_rank(MPI_COMM_WORLD, &rank);
             return rank;
           } ();

  m_size = [] () {
             int size=0;
             MPI_Comm_size(MPI_COMM_WORLD, &size);
             return size;
           } ();

  if (m_rank != 0) {
    // LCOV_EXCL_START
    pout.setOutput(null_stream);
    perr.setOutput(null_stream);
    // LCOV_EXCL_STOP
  }
#endif // PASTIS_HAS_MPI
}

Messenger::
~Messenger()
{
#ifdef PASTIS_HAS_MPI
  MPI_Finalize();
#endif // PASTIS_HAS_MPI
}

void Messenger::barrier() const
{
#ifdef PASTIS_HAS_MPI
  MPI_Barrier(MPI_COMM_WORLD);
#endif // PASTIS_HAS_MPI
}

} // namespace parallel