#include "libscl.h"
#include "mpi.h"
using namespace std;
using namespace scl;

namespace {

  int my_rank;         // Rank of process

  void mpi_error (string msg) {
    cout << msg << endl; MPI_Abort(MPI_COMM_WORLD, my_rank);
  }
  void mpi_warn (string msg) {
    cout << msg << endl; MPI_Abort(MPI_COMM_WORLD, my_rank);
  }

}

int main(int argc, char *argp[], char *envp[])
{

  const int buflen = 100;
  char buffer[buflen];    // Buffer for messages
  int no_procs;           // Number of processes
  int tag = 50;           // Tag for messages

  MPI_Init(&argc, &argp);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
  MPI_Comm_size(MPI_COMM_WORLD, &no_procs);

  LIB_ERROR_HANDLER_PTR previous_error = set_lib_error_handler(&mpi_error);
  LIB_WARN_HANDLER_PTR previous_warn = set_lib_warn_handler(&mpi_warn);

  if (my_rank != 0) { // Slave
    const bool use_C_style = false; 
    if (use_C_style) {    // using C style
      sprintf(buffer, "\tGreetings from process %d \n", my_rank);
    } 
    else {                // using C++ style
      stringstream ss;
      ss << "\tGreetings from process " << my_rank << '\n' << '\0';
      string s(ss.str());
      for (string::size_type i=0; i<s.size(); ++i) buffer[i] = s[i];
    }
    int dest = 0; 
    MPI_Send (buffer, buflen, MPI_CHAR, dest, tag, MPI_COMM_WORLD);  
  }
  else { // Master
    for (int source = 1; source < no_procs; ++source) { 
      MPI_Status status;
      MPI_Recv(buffer, buflen, MPI_CHAR, source, tag, MPI_COMM_WORLD, &status);
      cout << buffer;
    }
  }

  MPI_Finalize();

  previous_error = set_lib_error_handler(previous_error);
  previous_warn = set_lib_warn_handler(previous_warn);

}
