#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "charm++.h"
//#include "util.h"

#include "jacobi.h"
#include "jacobi90.h"

int M; // readonly variable. All global variables must be readonly. 

#include "jacobi.def.h"

CkArrayID arrayGroup;
main::main(CkArgMsg *m)
{ 
  globalInit(&M);

  arrayGroup = CProxy_jacobi::ckNew(M); // 1-D decomposition: array of 5 cells
  CkStartQD(EntryIndex(main,allDone,CkQdMsg), &thishandle);
};

void 
main::allDone(CkQdMsg *m)
{
  CkExit();
};

jacobi::jacobi()
{ 

 long obj = (long)this;
 chunkInit(&obj, (char **)&data, &thisIndex);
 sendToNeighbors(data);

};

jacobi::jacobi(ArrayElementMigrateMessage *m): receiver(m)
{
};


// c interface
extern "C" void 
c_irecv(receiver *op, char *buf, int count, int type, int tag, 
        int from, int refno)
{
  //CkPrintf("irecv from %d with ref %d\n", from, refno);
  op->irecv(buf, count, type, from, tag, refno); 
}

extern "C" void 
c_iwaitall(receiver *op, recvCallBack f, void *cb_data, int refno)
{
  op->iwaitAll(f, cb_data, refno);
}

extern "C" int typesize(int, int);

extern "C" void 
c_send(receiver *op, int index, char *buf, int count, int type, int tag, 
       int refno)
{
  //CkPrintf("isend to %d with ref %d\n", index, refno);
  op->isend(buf, count, type, index, tag, refno);
}

// fortran interface
extern "C" void 
f_irecv(long *obj, char *buf, int *count, int *type, int *tag, int *from, 
        int *refno)
{
  receiver *op = (jacobi*)*obj; 
  c_irecv(op, buf, *count, *type, *tag, *from, *refno);
}

extern "C" void 
f_iwaitall(long *obj, void *f, void *cb_data, int *refno)
{
  receiver *op = (jacobi*)*obj;
  c_iwaitall(op, (recvCallBack)f, cb_data, *refno);
}

extern "C" void 
f_send(long *obj, int *index, char *buf, int *count, int *type, int *tag,
       int *refno)
{
  receiver *op = (jacobi*)*obj;
  c_send(op, *index, buf, *count, *type, *tag, *refno);
}

// for migration, need to write pack interface.


// for debug
extern "C" void 
myprint_(int *i)
{
  CkPrintf("printout: %p. \n", i);
}

