#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "eegdef.h"
#include "sethead.h"

#define HEADSIZE 900
#define CHANSIZE  75
#define EVT1SIZE   8
#define TEEGSIZE   9

char mychar(char *);
short myshort(char *);
int myint(char *);
long mylong(char *);
float myfloat(char *);
double mydouble(char *);
unsigned char myuchar(char *);
unsigned short myushort(char *);

extern void writeHeadInfo(SETUP *);
extern void writeChanInfo(SETUP *);
extern void writeTEEGinfo(TEEG  *);

void readChanInfo(FILE *, ELECTLOC *);
void readHeadInfo(FILE *, SETUP *);
int readTEEGinfo(TEEG *, FILE *);

SETUP *readInfo(FILE *fptr) {
   SETUP *erp;
   int numChans, i;
   long totalMemory;

   if ( ( erp = (SETUP *)malloc(sizeof(SETUP)) ) == NULL ) {
	  fprintf(stderr,"Unable to allocate header memory!\n");
	  exit(1);
   }

   readHeadInfo(fptr, erp);      /* initial read */

   numChans = erp->nchannels;
   totalMemory = sizeof(SETUP) + sizeof(ELECTLOC)*numChans;
   free(erp);

   if ( ( erp = (SETUP *)malloc( totalMemory ) ) == NULL ) {
      fprintf(stderr,"Unable to allocate header and channel memory!\n");
	  exit(1);
   }

   fseek( fptr, 0, 0 );         /* rewind file pointer to beginning */
   readHeadInfo(fptr, erp);

   for ( i = 0; i < numChans; i++ )
      readChanInfo( fptr, &(erp->elect_tab[i]) );

   return erp;
}

void readChanInfo(FILE *fp, ELECTLOC *sp) {
   char buffer[1024];
   char *cp;

   if ( fread(buffer,75,1,fp) != 1 ) {      /* read 75 bytes into cp */
	  fprintf(stderr,"Unable to read channel information!\n");
	  exit(1);
   }

   cp = buffer;

   strncpy(sp->lab,cp,10);           cp += 10;  /* string: 10 chars */
   sp->reference     = mychar(cp);   cp += 1;   /* char */
   sp->skip          = mychar(cp);   cp += 1;   /* char */
   sp->reject        = mychar(cp);   cp += 1;   /* char */
   sp->display       = mychar(cp);   cp += 1;   /* char */
   sp->bad           = mychar(cp);   cp += 1;   /* char */
   sp->n             = myushort(cp); cp += 2;   /* unsigned short */
   sp->avg_reference = mychar(cp);   cp += 1;   /* char */
   sp->ClipAdd       = mychar(cp);   cp += 1;   /* char */
   sp->x_coord       = myfloat(cp);  cp += 4;   /* float */
   sp->y_coord       = myfloat(cp);  cp += 4;   /* float */
   sp->veog_wt       = myfloat(cp);  cp += 4;   /* float */
   sp->veog_std      = myfloat(cp);  cp += 4;   /* float */
   sp->snr           = myfloat(cp);  cp += 4;   /* float */
   sp->heog_wt       = myfloat(cp);  cp += 4;   /* float */
   sp->heog_std      = myfloat(cp);  cp += 4;   /* float */
   sp->baseline      = myshort(cp);  cp += 2;   /* short */
   sp->Filtered      = mychar(cp);   cp += 1;   /* char */
   sp->Fsp           = mychar(cp);   cp += 1;   /* char */
   sp->aux1_wt       = myfloat(cp);  cp += 4;   /* float */
   sp->aux1_std      = myfloat(cp);  cp += 4;   /* float */
   sp->sensitivity   = myfloat(cp);  cp += 4;   /* float */
   sp->Gain          = mychar(cp);   cp += 1;   /* char */
   sp->HiPass        = mychar(cp);   cp += 1;   /* char */
   sp->LoPass        = mychar(cp);   cp += 1;   /* char */
   sp->Page          = myuchar(cp);  cp += 1;   /* unsigned char */
   sp->Size          = myuchar(cp);  cp += 1;   /* unsigned char */
   sp->Impedance     = myuchar(cp);  cp += 1;   /* unsigned char */
   sp->PhysicalChnl  = myuchar(cp);  cp += 1;   /* unsigned char */
   sp->Rectify       = mychar(cp);   cp += 1;   /* char */
   sp->calib         = myfloat(cp);  cp += 4;   /* float */
}


void readHeadInfo(FILE *fp, SETUP *sp) {
   char buffer[1024];
   char *cp;

   if ( fread(buffer,900,1,fp) != 1 ) {     /* read 900 bytes into cp */
	  fprintf(stderr,"Unable to read header information!\n");
	  exit(1);
   }

   cp = buffer;

   strncpy(sp->rev,cp,20);               cp += 20;     /* string:20 chars */
   sp->type             = mychar(cp);    cp += 1;      /* char */
   strncpy(sp->id,cp,20);                cp += 20;     /* string:20 chars */
   strncpy(sp->oper,cp,20);              cp += 20;     /* string:20 chars */
   strncpy(sp->doctor,cp,20);            cp += 20;     /* string:20 chars */
   strncpy(sp->referral,cp,20);          cp += 20;     /* string:20 chars */
   strncpy(sp->hospital,cp,20);          cp += 20;     /* string:20 chars */
   strncpy(sp->patient,cp,20);           cp += 20;     /* string:20 chars */
   sp->age              = myshort(cp);   cp += 2;      /* short int */
   sp->sex              = mychar(cp);    cp += 1;      /* char */
   sp->hand             = mychar(cp);    cp += 1;      /* char */
   strncpy(sp->med,cp,20);               cp += 20;     /* string:20 chars */
   strncpy(sp->class,cp,20);             cp += 20;     /* string:20 chars */
   strncpy(sp->state,cp,20);             cp += 20;     /* string:20 chars */
   strncpy(sp->label,cp,20);             cp += 20;     /* string:20 chars */
   strncpy(sp->date,cp,10);              cp += 10;     /* string:10 chars */
   strncpy(sp->time,cp,12);              cp += 12;     /* string:12 chars */
   sp->mean_age         = myfloat(cp);   cp += 4;      /* float */
   sp->stdev            = myfloat(cp);   cp += 4;      /* float */
   sp->n                = myshort(cp);   cp += 2;      /* short int */
   strncpy(sp->compfile,cp,20);          cp += 38;     /* string:38 chars */
   sp->SpectWinComp     = myfloat(cp);   cp += 4;      /* float */
   sp->MeanAccuracy     = myfloat(cp);   cp += 4;      /* float */
   sp->MeanLatency      = myfloat(cp);   cp += 4;      /* float */
   strncpy(sp->sortfile,cp,20);          cp += 46;     /* string:46 chars */
   sp->NumEvents        = myint(cp);     cp += 4;      /* int */
   sp->compoper         = mychar(cp);    cp += 1;      /* char */
   sp->avgmode          = mychar(cp);    cp += 1;      /* char */
   sp->review           = mychar(cp);    cp += 1;      /* char */
   sp->nsweeps          = myushort(cp);  cp += 2;      /* unsigned short */
   sp->compsweeps       = myushort(cp);  cp += 2;      /* unsigned short */
   sp->acceptcnt        = myushort(cp);  cp += 2;      /* unsigned short */
   sp->rejectcnt        = myushort(cp);  cp += 2;      /* unsigned short */
   sp->pnts             = myushort(cp);  cp += 2;      /* unsigned short */
   sp->nchannels        = myushort(cp);  cp += 2;      /* unsigned short */
   sp->avgupdate        = myushort(cp);  cp += 2;      /* unsigned short */
   sp->domain           = mychar(cp);    cp += 1;      /* char */
   sp->variance         = mychar(cp);    cp += 1;      /* char */
   sp->rate             = myushort(cp);  cp += 2;      /* unsigned short */
   sp->scale            = mydouble(cp);  cp += 8;      /* double */
   sp->veogcorrect      = mychar(cp);    cp += 1;      /* char */
   sp->heogcorrect      = mychar(cp);    cp += 1;      /* char */
   sp->aux1correct      = mychar(cp);    cp += 1;      /* char */
   sp->aux2correct      = mychar(cp);    cp += 1;      /* char */
   sp->veogtrig         = myfloat(cp);   cp += 4;      /* float */
   sp->heogtrig         = myfloat(cp);   cp += 4;      /* float */
   sp->aux1trig         = myfloat(cp);   cp += 4;      /* float */
   sp->aux2trig         = myfloat(cp);   cp += 4;      /* float */
   sp->heogchnl         = myshort(cp);   cp += 2;      /* short int */
   sp->veogchnl         = myshort(cp);   cp += 2;      /* short int */
   sp->aux1chnl         = myshort(cp);   cp += 2;      /* short int */
   sp->aux2chnl         = myshort(cp);   cp += 2;      /* short int */
   sp->veogdir          = mychar(cp);    cp += 1;      /* char */
   sp->heogdir          = mychar(cp);    cp += 1;      /* char */
   sp->aux1dir          = mychar(cp);    cp += 1;      /* char */
   sp->aux2dir          = mychar(cp);    cp += 1;      /* char */
   sp->veog_n           = myshort(cp);   cp += 2;      /* short int */
   sp->heog_n           = myshort(cp);   cp += 2;      /* short int */
   sp->aux1_n           = myshort(cp);   cp += 2;      /* short int */
   sp->aux2_n           = myshort(cp);   cp += 2;      /* short int */
   sp->veogmaxcnt       = myshort(cp);   cp += 2;      /* short int */
   sp->heogmaxcnt       = myshort(cp);   cp += 2;      /* short int */
   sp->aux1maxcnt       = myshort(cp);   cp += 2;      /* short int */
   sp->aux2maxcnt       = myshort(cp);   cp += 2;      /* short int */
   sp->veogmethod       = mychar(cp);    cp += 1;      /* char */
   sp->heogmethod       = mychar(cp);    cp += 1;      /* char */
   sp->aux1method       = mychar(cp);    cp += 1;      /* char */
   sp->aux2method       = mychar(cp);    cp += 1;      /* char */
   sp->AmpSensitivity   = myfloat(cp);   cp += 4;      /* float */
   sp->LowPass          = mychar(cp);    cp += 1;      /* char */
   sp->HighPass         = mychar(cp);    cp += 1;      /* char */
   sp->Notch            = mychar(cp);    cp += 1;      /* char */
   sp->AutoClipAdd      = mychar(cp);    cp += 1;      /* char */
   sp->baseline         = mychar(cp);    cp += 1;      /* char */
   sp->offstart         = myfloat(cp);   cp += 4;      /* float */
   sp->offstop          = myfloat(cp);   cp += 4;      /* float */
   sp->reject           = mychar(cp);    cp += 1;      /* char */
   sp->rejstart         = myfloat(cp);   cp += 4;      /* float */
   sp->rejstop          = myfloat(cp);   cp += 4;      /* float */
   sp->rejmin           = myfloat(cp);   cp += 4;      /* float */
   sp->rejmax           = myfloat(cp);   cp += 4;      /* float */
   sp->trigtype         = mychar(cp);    cp += 1;      /* char */
   sp->trigval          = myfloat(cp);   cp += 4;      /* float */
   sp->trigchnl         = mychar(cp);    cp += 1;      /* char */
   sp->trigmask         = myshort(cp);   cp += 2;      /* short int */
   sp->trigisi          = myfloat(cp);   cp += 4;      /* float */
   sp->trigmin          = myfloat(cp);   cp += 4;      /* float */
   sp->trigmax          = myfloat(cp);   cp += 4;      /* float */
   sp->trigdir          = mychar(cp);    cp += 1;      /* char */
   sp->Autoscale        = mychar(cp);    cp += 1;      /* char */
   sp->n2               = myshort(cp);   cp += 2;      /* short int */
   sp->dir              = mychar(cp);    cp += 1;      /* char */
   sp->dispmin          = myfloat(cp);   cp += 4;      /* float */
   sp->dispmax          = myfloat(cp);   cp += 4;      /* float */
   sp->xmin             = myfloat(cp);   cp += 4;      /* float */
   sp->xmax             = myfloat(cp);   cp += 4;      /* float */
   sp->AutoMin          = myfloat(cp);   cp += 4;      /* float */
   sp->AutoMax          = myfloat(cp);   cp += 4;      /* float */
   sp->zmin             = myfloat(cp);   cp += 4;      /* float */
   sp->zmax             = myfloat(cp);   cp += 4;      /* float */
   sp->lowcut           = myfloat(cp);   cp += 4;      /* float */
   sp->highcut          = myfloat(cp);   cp += 4;      /* float */
   sp->common           = mychar(cp);    cp += 1;      /* char */
   sp->savemode         = mychar(cp);    cp += 1;      /* char */
   sp->manmode          = mychar(cp);    cp += 1;      /* char */
   strncpy(sp->ref,cp,10);               cp += 10;     /* string:10 chars */
   sp->Rectify          = mychar(cp);    cp += 1;      /* char */
   sp->DisplayXmin      = myfloat(cp);   cp += 4;      /* float */
   sp->DisplayXmax      = myfloat(cp);   cp += 4;      /* float */
   sp->phase            = mychar(cp);    cp += 1;      /* char */
   strncpy(sp->screen,cp,16);            cp += 16;     /* string:16 chars */
   sp->CalMode          = myshort(cp);   cp += 2;      /* short int */
   sp->CalMethod        = myshort(cp);   cp += 2;      /* short int */
   sp->CalUpdate        = myshort(cp);   cp += 2;      /* short int */
   sp->CalBaseline      = myshort(cp);   cp += 2;      /* short int */
   sp->CalSweeps        = myshort(cp);   cp += 2;      /* short int */
   sp->CalAttenuator    = myfloat(cp);   cp += 4;      /* float */
   sp->CalPulseVolt     = myfloat(cp);   cp += 4;      /* float */
   sp->CalPulseStart    = myfloat(cp);   cp += 4;      /* float */
   sp->CalPulseStop     = myfloat(cp);   cp += 4;      /* float */
   sp->CalFreq          = myfloat(cp);   cp += 4;      /* float */
   strncpy(sp->taskfile,cp,34);          cp += 34;     /* string:34 chars */
   strncpy(sp->seqfile,cp,34);           cp += 34;     /* string:34 chars */
   sp->SpectMethod      = mychar(cp);    cp += 1;      /* char */
   sp->SpectScaling     = mychar(cp);    cp += 1;      /* char */
   sp->SpectWindow      = mychar(cp);    cp += 1;      /* char */
   sp->SpectWinLength   = myfloat(cp);   cp += 4;      /* float */
   sp->SpectOrder       = mychar(cp);    cp += 1;      /* char */
   sp->NotchFilter      = mychar(cp);    cp += 1;      /* char */
   strncpy(sp->unused,cp,11);            cp += 11;     /* string:11 chars */
   sp->FspStopMethod    = myshort(cp);   cp += 2;      /* short int */
   sp->FspStopMode      = myshort(cp);   cp += 2;      /* short int */
   sp->FspFValue        = myfloat(cp);   cp += 4;      /* float */
   sp->FspPoint         = myshort(cp);   cp += 2;      /* short int */
   sp->FspBlockSize     = myshort(cp);   cp += 2;      /* short int */
   sp->FspP1            = myshort(cp);   cp += 2;      /* unsigned short */
   sp->FspP2            = myshort(cp);   cp += 2;      /* unsigned short */
   sp->FspAlpha         = myfloat(cp);   cp += 4;      /* float */
   sp->FspNoise         = myfloat(cp);   cp += 4;      /* float */
   sp->FspV1            = myshort(cp);   cp += 2;      /* short int */
   strncpy(sp->montage,cp,40);           cp += 40;     /* string:40 chars */
   strncpy(sp->EventFile,cp,40);         cp += 40;     /* string:40chars */
   sp->fratio           = myfloat(cp);   cp += 4;      /* float */
   sp->minor_rev        = mychar(cp);    cp += 1;      /* char */
   sp->eegupdate        = myshort(cp);   cp += 2;      /* short int */
   sp->compressed       = mychar(cp);    cp += 1;      /* char */
   sp->xscale           = myfloat(cp);   cp += 4;      /* float */
   sp->yscale           = myfloat(cp);   cp += 4;      /* float */
   sp->xsize            = myfloat(cp);   cp += 4;      /* float */
   sp->ysize            = myfloat(cp);   cp += 4;      /* float */
   sp->ACmode           = mychar(cp);    cp += 1;      /* char */
   sp->CommonChnl       = myuchar(cp);   cp += 1;      /* unsigned char */
   sp->Xtics            = mychar(cp);    cp += 1;      /* char */
   sp->Xrange           = mychar(cp);    cp += 1;      /* char */
   sp->Ytics            = mychar(cp);    cp += 1;      /* char */
   sp->Yrange           = mychar(cp);    cp += 1;      /* char */
   sp->XScaleValue      = myfloat(cp);   cp += 4;      /* float */
   sp->XScaleInterval   = myfloat(cp);   cp += 4;      /* float */
   sp->YScaleValue      = myfloat(cp);   cp += 4;      /* float */
   sp->YScaleInterval   = myfloat(cp);   cp += 4;      /* float */
   sp->ScaleToolX1      = myfloat(cp);   cp += 4;      /* float */
   sp->ScaleToolY1      = myfloat(cp);   cp += 4;      /* float */
   sp->ScaleToolX2      = myfloat(cp);   cp += 4;      /* float */
   sp->ScaleToolY2      = myfloat(cp);   cp += 4;      /* float */
   sp->port             = myshort(cp);   cp += 2;      /* short int */
   sp->NumSamples       = mylong(cp);    cp += 4;      /* long */
   sp->FilterFlag       = mychar(cp);    cp += 1;      /* char */
   sp->LowCutoff        = myfloat(cp);   cp += 4;      /* float */
   sp->LowPoles         = myshort(cp);   cp += 2;      /* short int */
   sp->HighCutoff       = myfloat(cp);   cp += 4;      /* float */
   sp->HighPoles        = myshort(cp);   cp += 2;      /* short int */
   sp->FilterType       = mychar(cp);    cp += 1;      /* char */
   sp->FilterDomain     = mychar(cp);    cp += 1;      /* char */
   sp->SnrFlag          = mychar(cp);    cp += 1;      /* char */
   sp->CoherenceFlag    = mychar(cp);    cp += 1;      /* char */
   sp->ContinousType    = mychar(cp);    cp += 1;      /* char */
   sp->EventTablePos    = mylong(cp);    cp += 4;      /* long */
   sp->ContinousSeconds = myfloat(cp);   cp += 4;      /* float */
   sp->ChannelOffset    = mylong(cp);    cp += 4;      /* long */
   sp->AutoCorrectFlag  = mychar(cp);    cp += 1;      /* char */
   sp->DCThreshold      = myuchar(cp);   cp += 1;      /* unsigned char */
   sp->elect_tab[N_ELECT];
}

int readTEEGinfo(TEEG *teeg, FILE *fp) {
   char teegBuf[TEEGSIZE];
   char *ptr;

   if ( (int)fread(teegBuf,TEEGSIZE,1,fp) != 1 ) {
      fprintf(stderr,"Unable to read %d bytes...\n", TEEGSIZE);
	  return 0;
   }
   ptr = teegBuf;

   teeg->Teeg = (int)*ptr;       ptr += 1;           /* enums are 1 byte!!! */
   teeg->Size = mylong(ptr);     ptr += 4;
   teeg->u.Offset = mylong(ptr);

   return 1;
}

int readEvent1Info(EVENT1 *evt, FILE *fp) {
   char evt1Buf[1024];
   char *ptr;

   if ( (int)fread(evt1Buf,EVT1SIZE,1,fp) != 1 ) {
	  return 0;
   }
   ptr = evt1Buf;

   evt->StimType = myushort(ptr);   ptr += 2;
   evt->KeyBoard = mychar(ptr);     ptr += 1;
   evt->KeyPad = (*ptr & 0x0f);   
   evt->Accept = (*ptr & 0xf0)>>4;  ptr += 1;
   evt->Offset = mylong(ptr);

   return 1;
}

short myshort(char *ptr) {
   unsigned char buffer[2];
   void *vp = (void *)buffer;

   buffer[0] = *(ptr+1); buffer[1] = *(ptr+0);

   return *(short *)vp;
}

int myint(char *ptr) {
   unsigned char buffer[4];
   void *vp = (void *)buffer;

   buffer[0] = *(ptr+3); buffer[1] = *(ptr+2); 
   buffer[2] = *(ptr+1); buffer[3] = *(ptr+0);

   return *(int *)vp;
}

long mylong(char *ptr) {
   unsigned char buffer[4];
   void *vp = (void *)buffer;

   buffer[0] = *(ptr+3); buffer[1] = *(ptr+2); 
   buffer[2] = *(ptr+1); buffer[3] = *(ptr+0);

   return *(long *)vp;
}

float myfloat(char *ptr) {
   unsigned char buffer[4];
   void *vp = (void *)buffer;

   buffer[0] = *(ptr+3); buffer[1] = *(ptr+2); 
   buffer[2] = *(ptr+1); buffer[3] = *(ptr+0);

   return *(float *)vp;
}

double mydouble(char *ptr) {
   unsigned char buffer[4];
   void *vp = (void *)buffer;

   buffer[0] = *(ptr+7); buffer[1] = *(ptr+6); 
   buffer[2] = *(ptr+5); buffer[3] = *(ptr+4);
   buffer[4] = *(ptr+3); buffer[5] = *(ptr+2); 
   buffer[6] = *(ptr+1); buffer[7] = *(ptr+0);

   return *(double *)buffer;
}

unsigned char myuchar(char *ptr) {
   unsigned char character = (unsigned char)*ptr;

   return character;
}

char mychar(char *ptr) {
   char character = *ptr;

   return character;
}

unsigned short myushort(char *ptr) {
   unsigned char buffer[2];
   void *vp = (void *)buffer;

   buffer[0] = *(ptr+1); buffer[1] = *(ptr+0);

   return *(unsigned short *)buffer;
}


