#include "mex.h"
#include "matrix.h"
#include "wfdb/wfdb.h"
#include <string.h>

/*
 * WFDB_getann.c
 *
 * Get annotations.
 *
 */
 
/* Define order of input variables */
#define ANNOTATOR_INPUT 0
#define NUM_INPUT 1

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

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  const char **fnames;
  unsigned int mrows, i, c, ann_num;
  WFDB_Annotation annotation;
  char *aux;
  mxArray *temp;
  unsigned int first_ann;
  int err_code;

  /* Check for proper number of input arguments. */
  if (nrhs < 1)
    mexErrMsgTxt("At least one input argument required.");

  /* Get ANNOTATOR_INPUT */
  ann_num = *mxGetPr(prhs[ANNOTATOR_INPUT]);

  /* Create field names for output structure */
  fnames = mxCalloc(6, sizeof(*fnames));
  fnames[0] = "time";
  fnames[1] = "anntyp";
  fnames[2] = "subtyp";
  fnames[3] = "chan";
  fnames[4] = "num";
  fnames[5] = "aux";

  /* Find the size of the output matrix */
  if ((err_code = getann(ann_num, &annotation)) < 0)
    switch (err_code)
      {
      case -1:
	mexErrMsgTxt("End of file");
      case -2:
	mexErrMsgTxt("Failure: incorrect annotator number specified");
      case -3:
	mexErrMsgTxt("Failure: unexpected physical end of file");
      default:
	mexPrintf("Error code: %d\n", err_code);
	mexErrMsgTxt("Unknown error");
      }
  first_ann = annotation.time;
  mrows = 1;
  while ((err_code = getann(ann_num, &annotation)) == 0)
    mrows++;
  if (err_code != -1)
    if (err_code == -3)
      mexErrMsgTxt("Failure: unexpected physical end of file");
    else
      {
	mexPrintf("Error code: %d\n", err_code);
	mexErrMsgTxt("Unknown error");
      }
  iannsettime(first_ann);

  if (nrhs == 2)
    if (mrows > *mxGetPr(prhs[NUM_INPUT]))
      mrows = *mxGetPr(prhs[NUM_INPUT]);

  /* Create output structure */
  plhs[ANN_OUTPUT] = mxCreateStructMatrix(mrows, 1, 6, fnames);

  /* Fill output structure */
  for (i = 0; i < mrows; i++)
    {
      getann(ann_num, &annotation);

      mxSetField(plhs[ANN_OUTPUT], i, "time", 
		 mxCreateDoubleScalar(annotation.time));

      mxSetField(plhs[ANN_OUTPUT], i, "anntyp", 
		 mxCreateDoubleScalar(annotation.anntyp));

      mxSetField(plhs[ANN_OUTPUT], i, "subtyp", 
		 mxCreateDoubleScalar(annotation.subtyp));

      mxSetField(plhs[ANN_OUTPUT], i, "chan", 
		 mxCreateDoubleScalar(annotation.chan));

      mxSetField(plhs[ANN_OUTPUT], i, "num", 
		 mxCreateDoubleScalar(annotation.num));

      if (annotation.aux != NULL)
	{
	  aux = mxCalloc(strlen(annotation.aux), sizeof(char));
	  strcpy(aux, annotation.aux);
	  for (c = 0; c < (strlen(aux) - 1); c++)
	    aux[c] = aux[c+1];
	  aux[strlen(aux) - 1] = '\0';
	  mxSetField(plhs[ANN_OUTPUT], i, "aux", mxCreateString(aux));
	}
      else
	mxSetField(plhs[ANN_OUTPUT], i, "aux", mxCreateString(""));
    }
}
