#ifndef JacobiLB_H
#define JacobiLB_H

#include "JacobiLB.decl.h"

void CreateJacobiLB();

typedef struct {
double cputime;
double walltime;
} LoadData;

/*
class StrCreateMsg: public CMessage_StrCreateMsg {
public:
int funcIdx;
CkChareID mainhandle;
};
*/

class objDataMsg : public CMessage_objDataMsg {
public:
double cputime;
double walltime;
int pe;
};

class BalSoonMsg : public CMessage_BalSoonMsg {
public:
};

#define MAX_PE  256

class stgyMsg : public CMessage_stgyMsg {
public:
double averageCPU;
double averageWall;
double load[MAX_PE];
int num;
};

class BalTriggerMsg : public CMessage_BalTriggerMsg {
public:
  int step;
};

class JacobiLB : public Group
{
private:
  //
/*
  LBDBHandle lbdb;
  OMHandle lbom;
  SyncHandle syncHand;
  SyncCltHandle recver;
*/

  int numObj;
  LDObjData *lbdata;

  int curBalStep;
  int nextBalStep;
  int loadBalanceSoon;
  int loadBalanceInProgress;

  // for quiescence
  int funcIdx;
  CkChareID mainhandle;

  // only used by processor 0
  int count;
  LoadData *array;
  int maxBalStep;
  int balanceCount;

  void RandomMigrate(stgyMsg *);
  void BetterRandomMigrate(stgyMsg *);
  double min(double x, double y) { return (x < y) ? x : y; };
  double SendTo(double transfer, int to, int *already_migratable);

protected:
  LBDatabase* theLbdb;

public:
//  JacobiLB(StrCreateMsg *);
  JacobiLB();
  JacobiLB(CkMigrateMessage *m) {}
  ~JacobiLB();
  static void staticMigrated(void* data, LDObjHandle h);
  void Migrated(LDObjHandle h);
  static void staticAtSync(void* data);
  void AtSync();
  void resumeLocalCells();
  void QuiesResume();
  void balanceNow(void);
  void collectStatis(objDataMsg *);
  void migrate(stgyMsg *);
  void BalanceSoon(BalSoonMsg *m);
  void BalanceSync(BalTriggerMsg *m);
  void NextBalance(BalTriggerMsg *m);


/*
  // local
  LBDBHandle getLBDBHandle() { return lbdb; };
  OMHandle getOMHandle() { return lbom; };
  SyncHandle getPESyncHandle() { return syncHand; };
*/
};


#endif
