#include "mex.h"
#include "matrix.h"
#include "wfdb/wfdb.h"

/*
 * WFDB_getframe.c
 *
 * Get data from a Physionet record.
 *
 */
 
/* Define order of input variables */
#define NSIG_INPUT 0
#define NSAMP_INPUT 1
#define TSTART_INPUT 2

/* Define order of output variables */
#define DATA_OUTPUT 0

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  unsigned int ncols, i;
  unsigned long mrows, t, tstart;
  int err_code;
  double *data;
  WFDB_Sample *v;

  /* Check for correct number of input arguments. */
  if (nrhs < 1)
    mexErrMsgTxt("At least one input argument.");
  else if (nrhs > 3)
    mexErrMsgTxt("Too many input arguments");

  /* Get number of signals and create Sample vector */
  ncols = *mxGetPr(prhs[NSIG_INPUT]);
  v = (WFDB_Sample *)mxMalloc(ncols * sizeof(WFDB_Sample));

  if (nrhs == 1)
    {
      /* Get number of samples */
      isigsettime(0);
      mrows = 0;
      while ( (err_code = getvec(v)) > 0 )
	mrows++;

      /* Reset signal file pointer to 0 */
      isigsettime(0);
    }
  else {
    mrows = *mxGetPr(prhs[NSAMP_INPUT]);
    if (nrhs > 2) {
	tstart = *mxGetPr(prhs[TSTART_INPUT]);
	isigsettime(tstart);
    }
  }

  /* Create DATA output matrix */
  plhs[DATA_OUTPUT] = mxCreateDoubleMatrix(mrows, ncols, mxREAL);
  data = mxGetPr(plhs[DATA_OUTPUT]);

  /* Fill DATA matrix */
  for (t = 0; t < mrows; t++)
    {
      err_code = getframe(v);
      if (err_code < 0)
	switch (err_code)
	  {
	  case -3:
	    mexErrMsgTxt("Failure: unexpected physical end of file");
	  case -4:
	    mexErrMsgTxt("Failure: checksum error");
	  default:
	    mexPrintf("Error code: %d\n", err_code);
	    mexErrMsgTxt("Unexpected Failure");
	  }
      for (i = 0; i < ncols; i++)
	*(data + i*mrows + t) = v[i];
    }

  mxFree(v);
}
