#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <math.h>
#include <stdbool.h>

#include "cdi.h"
#include "resource_handle.h"
/* FIXME: no longer needed when taxis updates are sent as separate data */
#include "taxis.h"

#include "pio_interface.h"
#include "pio_rpc.h"

struct clientBufSize
computeClientStreamBufSize(int streamID, const struct collSpec *collector)
{
  /* 1 record is filled in last to indicate number of records in total */
  struct clientBufSize rmaSizeSpec = { .bufSize = sizeof(struct winHeaderEntry), .numDataRecords = 1, .numRPCRecords = 0 };
  int vlistID = streamInqVlist(streamID);
  size_t nvars = (size_t) vlistNvars(vlistID);
  for (size_t varID = 0; varID < nvars; ++varID)
    {
      size_t chunkSize;
      {
        int varSize = vlistInqVarSize(vlistID, (int) varID);
        chunkSize = (size_t) (ceilf(cdiPIOpartInflate_ * (float) varSize / (float) collector->numClients));
      }
      rmaSizeSpec.numDataRecords += 2;
      rmaSizeSpec.bufSize += chunkSize * sizeof(double)
                             /* re-align chunk to multiple of double size */
                             + sizeof(double)
                             - 1
                             /* one header for data record, one for corresponding part
                              * descriptor*/
                             + 2 * sizeof(struct winHeaderEntry)
                             /* FIXME: heuristic for size of packed Xt_idxlist */
                             + sizeof(Xt_int) * chunkSize * 3;
    }

  // memory required for the function calls encoded
  // for remote execution
  // once per stream and timestep for each collector process
  // from one model process
  if (collector->sendRPCData)
    {
      rmaSizeSpec.numRPCRecords = numRPCFuncs;
      rmaSizeSpec.bufSize += numRPCFuncs * sizeof(struct winHeaderEntry)
                             /* data part of streamDefTimestep */
                             + (2 * CDI_MAX_NAME + sizeof(taxis_t));
    }
  rmaSizeSpec.bufSize = roundUpToMultiple(rmaSizeSpec.bufSize, PIO_WIN_ALIGN);
  return rmaSizeSpec;
}
