#include "pgm.h"

CkChareID mainhandle;

UserClass::UserClass(void)
{
  CProxy_UserClass uc(thishandle);
  uc.doSendRecv();
}

void
UserClass::doSendRecv(void)
{
  CkChareID otherid;
  char inbuffer[100], outbuf[100];
  
  IdMsg *idmsg = new IdMsg(thishandle);

  CProxy_main mainproxy(mainhandle);
  mainproxy.getid(idmsg);

  ckTempoRecv(1, &otherid, sizeof(CkChareID));
  
  for (int i=0; i<10; i++) {
    sprintf(outbuf, "message %d sent from proc %d", i, CkMyPe()); 
    ckTempoSend(i+2, outbuf, strlen(outbuf) + 1, otherid);
    ckTempoRecv(i+2, inbuffer, 100);
    CkPrintf("chare[%d] received message : %s\n", CkMyPe(), inbuffer);
  }
  delete this;
}

void 
UserGroup::doSendRecv(void)
{
  char outbuf[100];
  sprintf(outbuf, "message broadcast from boc on proc %d", CkMyPe()); 
  ckTempoBcast(CkMyPe()==0, 1001, outbuf, strlen(outbuf)+1);
  CkPrintf("group[%d] received message : %s\n", CkMyPe(), outbuf);
  delete this;
}

void 
UserArray::doSendRecv(void)
{
  char outbuf[100], inbuf[100];
  sprintf(outbuf, "message sent from array[%d]", thisIndex); 
  ckTempoSendElem(thisIndex+12, outbuf, strlen(outbuf)+1, (thisIndex+1)%2);
  ckTempoRecv((thisIndex+1)%2+12, inbuf, 100);
  CkPrintf("array[%d] received message : %s\n", thisIndex, inbuf);
  sprintf(outbuf, "message bcast from array[%d]", thisIndex); 
  ckTempoBcast(thisIndex==0, 1012, outbuf, strlen(outbuf));
  CkPrintf("array[%d] received bcast message : %s\n", thisIndex, outbuf);
  int data = thisIndex+1;
  ckTempoReduce(0, TEMPO_SUM, (void *) &data, (void *) &data, 1, TEMPO_INT);
  if(thisIndex==0)
    CkPrintf("sum(1,%d) = %d\n", numElements, data);
  data = thisIndex+1;
  ckTempoAllReduce(TEMPO_PROD, (void *) &data, (void *) &data, 1, TEMPO_INT);
  CkPrintf("on array[%d], prod(1,%d) = %d\n", thisIndex, numElements, data);
  delete this;
}

void 
main::sendids(void)
{
  TempoChare::ckTempoSend(1, &(id2->id), sizeof(CkChareID), id1->id); 
  TempoChare::ckTempoSend(1, &(id1->id), sizeof(CkChareID), id2->id); 
  delete id1;
  delete id2;
}

main::main(CkArgMsg *)
{
  int bocid;
  id1 = id2 = 0;
  CProxy_UserGroup *pug = new CProxy_UserGroup();
  pug->doSendRecv();
  CProxy_UserClass::ckNew(0);
  CProxy_UserClass::ckNew(1);
  CkArrayID aid = CProxy_UserArray::ckNew(2);
  CProxy_UserArray pua(aid);
  pua[0].doSendRecv();
  pua[1].doSendRecv();
  CkStartQD(CProxy_main::ckIdx_Finish((CkQdMsg*)0), &thishandle);
  mainhandle = thishandle;
}

void 
main::Finish(CkQdMsg *)
{
  CkExit();
}

void 
main::getid(IdMsg *idmsg)
{
  if (id1 == 0)
    id1 = idmsg;
  else {
    id2 = idmsg;
    sendids();
  }
}
#include "pgm.def.h"
