#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"

CkAID 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);
  CkPrintf("main done\n");
};

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

jacobi::jacobi(ArrayElementCreateMessage *msg) : receiver(msg) 
{ 
 CkPrintf("[%d]: Element %d created\n", CkMyPe(), thisIndex); 
 int i = 10;
 int j= 100;
 long obj = (long)this;
 chunkInit(&obj, &i, &j, (char **)&data, &thisIndex);

 iterations = 0;
 sendToNeighbors(data);

 finishConstruction(); 
};

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


// c interface
extern "C" void c_irecv(jacobi *op, char *buf, int size, int tag, int from, int refno)
{
  op->irecv(buf, size, from, tag, refno);
}

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

extern "C" void c_send(int index, char *buf, int size, int tag, int from, int refno)
{
 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);
}

// fortran interface
extern "C" void f_irecv(long *obj, char *buf, int *size, int *tag, int *from, int *refno)
{
  CkPrintf("f_irecv: tag:%d from:%d refno:%d. \n", *tag, *from, *refno);
  jacobi *op = (jacobi*)*obj;
  c_irecv(op, buf, *size, *tag, *from, *refno);
}

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

extern "C" void f_send(int *index, char *buf, int *size, int *tag, int *from, int *refno)
{
  CkPrintf("f_send: index:%d tag:%d from:%d refno:%d. \n", *index, *tag, *from, *refno);
  c_send(*index, buf, *size, *tag, *from, *refno);
}

// for migration, need to write pack interface.


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




