#include <stdio.h>
#include "charm++.h"

//Have to define index type before we include "hello.decl"
class FancyIndex {
public:
	 int x,y,z;
	
	 FancyIndex() {}
	 FancyIndex(int Nx,int Ny,int Nz) {x=Nx;y=Ny;z=Nz;}
};

class CkArrayIndexFancy :public CkArrayIndex {
public:
	 FancyIndex f; 
	 CkArrayIndexFancy(int Nx,int Ny,int Nz):f(Nx,Ny,Nz) 
	   {nInts=3;}
};

#include "hello.decl.h"

CkChareID mid;
CProxy_Hello arr;
int nElem;

class HiMsg : public CMessage_HiMsg
{
  int data;
	 char foo[32];
};

class main : public Chare
{
public:
  main(CkMigrateMessage *m) {}
  main(CkArgMsg* m)
  {
    if(m->argc < 2) {
      CkAbort("Usage: hello <nElements>\n");
    }
    nElem = atoi(m->argv[1]);
    delete m;
    CkPrintf("Running Hello on %d processors for %d elements\n",
	     CkNumPes(),nElem);
    mid = thishandle;

    arr = CProxy_Hello::ckNew();

    for (int y=0;y<nElem;y++)
		 arr[CkArrayIndexFancy(37,y,2*y+1)].insert();
    arr.doneInserting();

    arr[CkArrayIndexFancy(37,0,2*0+1)].SayHi(new HiMsg);
  };

  void maindone(void)
  {
    CkPrintf("All done\n");
    CkExit();
  };
};

class Hello : public ArrayElementT<FancyIndex>
{
public:
  Hello(CkMigrateMessage *m) {}
  Hello()
  {
    CkPrintf("Hello %d created\n",thisIndex.y);
  }

  void SayHi(HiMsg *m)
  {
    CkPrintf("Hi from element %d\n",thisIndex.y);
    if (thisIndex.y < nElem-1) {
      int y=thisIndex.y+1;
      arr[CkArrayIndexFancy(37,y,2*y+1)].SayHi(m);
    } else {
      CProxy_main mproxy(mid);
      mproxy.maindone();
      delete m;
    }
  }
};

#include "hello.def.h"
