// communicate
//============

//! class to be written by use to pack/unpack data
class CommuncateDataHandle {
public:
  //! export type of data for message buffer
  typedef XX DataType;

  //! returns true if data for this codim should be communicated
  bool contains (int dim, int codim) const;

  //! pack data from user to message buffer
  template<class MessageBuffer, class EntityType>
  void gather (MessageBuffer& buff, const EntityType& e) const; 

  //! unpack data from message buffer to user
  template<class MessageBuffer, class EntityType>
  void scatter (const MessageBuffer& buff, const EntityType& e);

  //! how many objects of type DataType have to be sent
  template<class EntityType>
  size_t size (EntityType& e) const;
};

//! message buffer class exported by each grid
class MessageBuffer {
public:
  // write data to message buffer, acts like a stream !
  template<class DataType>
  void write (const DataType& data);

  // read data from message buffer, acts like a stream !
  template<class DataType>
  void read (DataType& data) const;
};


// in the grid class:
// ==================

//! levelwise communicate
template<class DataHandleVector>
void communicate (DataHandleVector& data, InterfaceType ifType, CommunicationDirection direction, int level) const;

//! leafwise communicate
template<class DataHandleVector>
void communicate (DataHandleVector& data, InterfaceType ifType, CommunicationDirection direction) const;

// ? all levels ?

// load balance
//=============

enum LoadBalanceIteratorRange {wholeGrid, leafGrid}; 

//! class to be written by use to pack/unpack data
class LoadBalanceDataHandle {
public:
  //! export type of data for message buffer
  typedef XX DataType;
  typedef YY BufferType;

  //! returns true if data for this codim should be communicated
  bool contains (int dim, int codim) const;

  //! return range where data is taken from
  IteratorRange range () const;

  //! pack data from user to message buffer
  template<class MessageBuffer, class EntityType>
  void pack (MessageBuffer& buff, const EntityType& e) const; 

  //! unpack data from message buffer to user
  template<class MessageBuffer, class EntityType>
  void unpack (const MessageBuffer& buff, const EntityType& e);

  //! how many objects of type DataType have to be sent
  template<class EntityType>
  size_t size (EntityType& e) const;

  //! access to buffer, is like STL vector. Contains newly arrived data
  BufferType& buffer ();
};


// in the grid class:
// ==================

/** @brief load balance the grid and communicate data

    The data object has already stored the access to the data on the old mesh
    (usually in a map, storing the old index)
 */
template<class DataHandleVector>
void loadBalance (DataHandleVector& data);

/** @brief Store transmitted data in the new places

    This function is called after the grid has been load balanced. The
    grid possibly stores the packed user data in internal buffers.
 */
template<class DataHandleVector>
void postLoadBalance (DataHandleVector& data) const;

