// Copyright 2016 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#include "maml.h"
#include "Context.h"

namespace maml {

using rkcommon::make_unique;

// maml API definitions /////////////////////////////////////////////////////

/*! start the service; from this point on maml is free to use MPI
    calls to send/receive messages; if your MPI library is not
    thread safe the app should _not_ do any MPI calls until 'stop()'
    has been called */
OSPRAY_MPI_COMMON_EXPORT void init(bool enableCompression)
{
  Context::singleton = make_unique<Context>(enableCompression);
}

/*! stops the maml layer; maml will no longer perform any MPI calls;
    if the mpi layer is not thread safe the app is then free to use
    MPI calls of its own, but it should not expect that this node
    receives any more messages (until the next 'start()' call) even
    if they are already in flight */
OSPRAY_MPI_COMMON_EXPORT void shutdown()
{
  Context::singleton = nullptr;
}

/*! register a new incoing-message handler. if any message comes in
  on the given communicator we'll call this handler */
OSPRAY_MPI_COMMON_EXPORT void registerHandlerFor(
    MPI_Comm comm, MessageHandler *handler)
{
  Context::singleton->registerHandlerFor(comm, handler);
}

OSPRAY_MPI_COMMON_EXPORT void start()
{
  Context::singleton->start();
}

OSPRAY_MPI_COMMON_EXPORT bool isRunning()
{
  return Context::singleton && Context::singleton->isRunning();
}

OSPRAY_MPI_COMMON_EXPORT void stop()
{
  Context::singleton->stop();
}

/*! send given message to given comm:rank. Once this function has
  called maml has full ownership of this message, and the user may
  no longer access it (because maml may delete it at any time) */
OSPRAY_MPI_COMMON_EXPORT void sendTo(
    MPI_Comm comm, int rank, std::shared_ptr<Message> msg)
{
  if (!(rank >= 0 && msg.get()))
    OSPRAY_THROW("Incorrect argument values given to maml::sendTo(...)");

  msg->rank = rank;
  msg->comm = comm;
  Context::singleton->send(msg);
}

OSPRAY_MPI_COMMON_EXPORT void queueCollective(std::shared_ptr<Collective> col)
{
  Context::singleton->queueCollective(col);
}

} // namespace maml
