#ifndef MPIWRAPPER_H
#define MPIWRAPPER_H

#if defined(_WIN32) || defined(_WIN64)

  #define MPICH_SKIP_MPICXX

#else // assume POSIX

  #define MPICH_SKIP_MPICXX

#endif

#include <stdlib.h>

#include "stdmpi.h"

#ifdef _MSC_VER
  typedef int BOOL;
  #define FALSE   0
  #define TRUE    1
#else
#endif

typedef signed    short sint16;
typedef unsigned  short uint16;

#ifdef _MSC_VER
  typedef signed    __int64       sint64;
  typedef unsigned  __int64       uint64;
#else
  typedef signed    long long int sint64;
  typedef unsigned  long long int uint64;

// kh 24.11.06 workaround for the scampi environment on arminius /opt/scali/include64/mpi.h
  #define MPI_UNSIGNED_LONG_LONG MPI_LONG_LONG_INT // kh 24.11.06 "ignore the sign during the transport" 
#endif

typedef struct
{
  int dummy;
} MPIWrapper;

void MPIWrapper_Destruct(MPIWrapper* pThis);

MPIWrapper* MPIWrapper_Instance(void);

int MPIWrapper_Init(MPIWrapper* pThis, int* argc, char*** argv);

int MPIWrapper_Finalize(MPIWrapper* pThis);

int MPIWrapper_Bcast(MPIWrapper* pThis, void* buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm);

int MPIWrapper_Comm_rank(MPIWrapper* pThis, MPI_Comm comm, int* rank);

int MPIWrapper_Comm_size(MPIWrapper* pThis, MPI_Comm comm, int* size);

int MPIWrapper_Get_processor_name(MPIWrapper* pThis, char* name, int* resultlen);

int MPIWrapper_Iprobe(MPIWrapper* pThis, int source, int tag, MPI_Comm comm, int* flag, MPI_Status* status);

int MPIWrapper_Isend(MPIWrapper* pThis, void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request* request);

int MPIWrapper_Probe(MPIWrapper* pThis, int source, int tag, MPI_Comm comm, MPI_Status* status);

int MPIWrapper_Wait(MPIWrapper* pThis, MPI_Request* request, MPI_Status* status);

int MPIWrapper_Pack(MPIWrapper* pThis, void* inbuf, int incount, MPI_Datatype datatype, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Recv(MPIWrapper* pThis, void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status* status);

int MPIWrapper_Send(MPIWrapper* pThis, void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm);

int MPIWrapper_Test(MPIWrapper* pThis, MPI_Request* request, int* flag, MPI_Status* status);

int MPIWrapper_Unpack(MPIWrapper* pThis, void* inbuf, int insize, int* position, void* outbuf, int outcount, MPI_Datatype datatype, MPI_Comm comm);

// kh 01.07.04 start extensions
int MPIWrapper_Pack_BOOL(MPIWrapper* pThis, BOOL bIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_USHORT(MPIWrapper* pThis, uint16 nIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_INT(MPIWrapper* pThis, int nIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_INT64(MPIWrapper* pThis, sint64 nIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_UINT64(MPIWrapper* pThis, uint64 nIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_DOUBLE(MPIWrapper* pThis, double nIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_STR(MPIWrapper* pThis, char* sIn, void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Pack_USHORT_ARRAY(MPIWrapper* pThis, int nLength, uint16 nIn[], void* outbuf, int outsize, int* position, MPI_Comm comm);

int MPIWrapper_Unpack_BOOL(MPIWrapper* pThis, void* inbuf, int insize, int* position, BOOL* pbOut, MPI_Comm comm);

int MPIWrapper_Unpack_USHORT(MPIWrapper* pThis, void* inbuf, int insize, int* position, uint16* pnOut, MPI_Comm comm);

int MPIWrapper_Unpack_INT(MPIWrapper* pThis, void* inbuf, int insize, int* position, int* pnOut, MPI_Comm comm);

int MPIWrapper_Unpack_INT64(MPIWrapper* pThis, void* inbuf, int insize, int* position, sint64* pnOut, MPI_Comm comm);

int MPIWrapper_Unpack_UINT64(MPIWrapper* pThis, void* inbuf, int insize, int* position, uint64* pnOut, MPI_Comm comm);

int MPIWrapper_Unpack_DOUBLE(MPIWrapper* pThis, void* inbuf, int insize, int* position, double* pnOut, MPI_Comm comm);

int MPIWrapper_Unpack_STR(MPIWrapper* pThis, void* inbuf, int insize, int* position, char* sOut, MPI_Comm comm);

int MPIWrapper_Unpack_USHORT_ARRAY(MPIWrapper* pThis, void* inbuf, int insize, int* position, int* pnLength, uint16 nOut[], MPI_Comm comm);
#endif
