#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;
CpvDeclare(receiver *, rmpiPtr);

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

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

void main::allDone(CkQdMsg *m)
{
  CkPrintf("Quiescence detected. stopping\n");
  CkExit();
};

jacobi::jacobi()
{ 
// CkPrintf("[%d]: Element %d created\n", CkMyPe(), thisIndex); 

 CpvInitialize(receiver *, rmpiPtr);
 CpvAccess(rmpiPtr) = this;

 int i = 10;
 int j= 100;
 long obj = (long)this;
 chunkInit(&obj, &i, &j, (char **)&data, &thisIndex);

 iterations = 0;
 sendToNeighbors(data);

};


// c interface
extern "C" void c_irecv(receiver *op, char *buf, int count, int type, int tag, int from, int 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(int index, char *buf, int count, int type, int tag, int from, int refno)
{
 int size = typesize(type, count);
 receiverMsg * d = new (&size, 0) receiverMsg;
 d->tag = tag;
 d->sendFrom = from;
 d->refno = refno;
 memcpy(d->buf, buf, size);
// CProxy_jacobi jarray(arrayGroup);
// jarray[index].generic(d);
 CProxy_receiver jarray(arrayGroup);
 jarray[index].generic(d);
}

// fortran interface
extern "C" void f_irecv(long *obj, char *buf, int *count, int *type, int *tag, int *from, int *refno)
{
//  CkPrintf("[%d] f_irecv: tag:%d from:%d refno:%d. \n", CkMyPe(), *tag, *from, *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(int *index, char *buf, int *count, int *type, int *tag, int *from, int *refno)
{
//  CkPrintf("[%d] f_send: index:%d tag:%d from:%d refno:%d. \n", CkMyPe(), *index, *tag, *from, *refno);
  c_send(*index, buf, *count, *type, *tag, *from, *refno);
}

// for migration, need to write pack interface.


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

