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

/* Define order of input variables */
#define RECORD_INPUT 0

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

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  const char **fnames;
  int nsig;
  char *record;
  unsigned int record_length, i;
  WFDB_Siginfo *siarray;
  mxArray *value;

  /* Check for correct total number of input arguments. */
  if (nrhs != 1)
    mexErrMsgTxt("One input argument required.");
      
  /* Create output structure with same fields as a WFDB_Siginfo */
  fnames = mxCalloc(14, sizeof(*fnames));
  fnames[0]  = "fname";
  fnames[1]  = "desc";
  fnames[2]  = "units";
  fnames[3]  = "gain";
  fnames[4]  = "initval";
  fnames[5]  = "group";
  fnames[6]  = "fmt";
  fnames[7]  = "spf";
  fnames[8]  = "bsize";
  fnames[9]  = "adcres";
  fnames[10] = "adczero";
  fnames[11] = "baseline";
  fnames[12] = "nsamp";
  fnames[13] = "cksum";

  /* RECORD input must be a string. */
  if (mxIsChar(prhs[RECORD_INPUT]) != 1)
    mexErrMsgTxt("RECORD must be a string.");

  /* Get the RECORD string. */
  record_length = (mxGetM(prhs[RECORD_INPUT]) *
		     mxGetN(prhs[RECORD_INPUT])) + 1;
  record = mxCalloc(record_length, sizeof(char));
  mxGetString(prhs[RECORD_INPUT], record, record_length);

  /* Get number of signals */
  nsig = isigopen(record, NULL, 0);
  if (nsig < 0)
    switch (nsig)
      {
      case -1:
	mexErrMsgTxt("Failure: unable to read header file");
      case -2:
	mexErrMsgTxt("Failure: incorrect header file format");
      default:
	mexPrintf("Error code: %d\n", nsig);
	mexErrMsgTxt("Unknown error");
      }
  siarray = (WFDB_Siginfo *)mxMalloc(nsig * sizeof(WFDB_Siginfo));

  /* Open input file */
  nsig = isigopen(record, siarray, nsig);

  /* Create output structure */
  plhs[STRUCT_OUTPUT] = mxCreateStructMatrix(nsig, 1, 14, fnames);

  /* Fill output structures */
  for (i = 0; i < nsig; i++)
    {
      mxSetField(plhs[0], i, "fname", mxCreateString(siarray[i].fname));

      mxSetField(plhs[0], i, "desc", mxCreateString(siarray[i].desc));

      mxSetField(plhs[0], i, "units", mxCreateString(siarray[i].units));

      mxSetField(plhs[0], i, "gain", 
		 mxCreateDoubleScalar(siarray[i].gain));

      mxSetField(plhs[0], i, "initval", 
		 mxCreateDoubleScalar(siarray[i].initval));

      mxSetField(plhs[0], i, "group", 
		 mxCreateDoubleScalar(siarray[i].group));

      mxSetField(plhs[0], i, "fmt", 
		 mxCreateDoubleScalar(siarray[i].fmt));

      mxSetField(plhs[0], i, "spf", 
		 mxCreateDoubleScalar(siarray[i].spf));

      mxSetField(plhs[0], i, "bsize", 
		 mxCreateDoubleScalar(siarray[i].bsize));

      mxSetField(plhs[0], i, "adcres", 
		 mxCreateDoubleScalar(siarray[i].adcres));

      mxSetField(plhs[0], i, "adczero", 
		 mxCreateDoubleScalar(siarray[i].adczero));

      mxSetField(plhs[0], i, "baseline", 
		 mxCreateDoubleScalar(siarray[i].baseline));

      mxSetField(plhs[0], i, "nsamp", 
		 mxCreateDoubleScalar(siarray[i].nsamp));

      mxSetField(plhs[0], i, "cksum", 
		 mxCreateDoubleScalar(siarray[i].cksum));

    }
}
