/*cntcat.c - concatenate GnuroScan continuous data files.
  Copyright (c) 1996 Matthew Belmonte

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

  If you find this program useful, please send mail to Matthew Belmonte.
  <mkb4@Cornell.edu>.  If you base a publication on data processed by this
  program, please notify Matthew Belmonte and include the following citation
  in your publication:

	Matthew Belmonte, `A Software System for Analysis of
	Steady-State Evoked Potentials', Association for Computing
	Machinery SIGBIO Newsletter 17:1:9-14 (April 1997).
*/

#define MAX_FILES 8
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#ifdef MSDOS
#  include <memory.h>
#else
#  include <unistd.h>
#endif
#include "intel.h"
#include "gnuro.h"

void main(argc, argv)
int argc;
char **argv;
  {
  register int file;
  register long event, file_offset_incr, i;
  short tmpbuf[100];
  FILE *(in[MAX_FILES]), *out;
  char hdr[MAX_FILES][packed_sizeof_SETUP], output_hdr[packed_sizeof_SETUP];
  char evt[MAX_FILES][packed_sizeof_TEEG], output_evt[packed_sizeof_TEEG];
  char evtbuf[packed_sizeof_EVENT2];
  printf("Copyright (c) 1996 Matthew Belmonte <mkb4@Cornell.edu>.  Please cite.\n");
  if(argc > MAX_FILES+2)
    {
    fprintf(stderr, "Recompile %s with MAX_FILES=%d\n", *argv, argc-2);
    exit(1);
    }
  if(argc < 4)
    {
    fprintf(stderr, "Usage: %s <infile> ... <infile> <outfile>\n", *argv);
    exit(1);
    }
  printf("Warning: This program does not correct for differences in calibration\n");
  printf("values.  You should use it only on data files that have been collected\n");
  printf("during the same recording session.\n");
/*open the zeroeth input file*/
  if((*in = fopen(argv[1],
#ifdef MSDOS
    "rb"
#else
    "r"
#endif
    )) == NULL)
    {
    perror(argv[1]);
    exit(errno);
    }
  fread(hdr[0], packed_sizeof_SETUP, 1, *in);
  fseek(*in, S_EventTablePos(hdr[0]), SEEK_SET);
  fread(evt[0], packed_sizeof_TEEG, 1, *in);
/*use the zeroeth file's main header and event table header as templates*/
  memcpy(output_hdr, hdr[0], packed_sizeof_SETUP);
  memcpy(output_evt, evt[0], packed_sizeof_TEEG);
  put_T_Offset(output_evt, 0L);
/*open the rest of the input files*/
  for(file = 1; file < argc-2; file++)
    {
  /*open input file*/
    if((in[file] = fopen(argv[file+1],
#ifdef MSDOS
      "rb"
#else
      "r"
#endif
      )) == NULL)
      {
      perror(argv[file+1]);
      while(file--)
	fclose(in[file]);
      exit(errno);
      }
  /*read file header*/
    fread(hdr[file], packed_sizeof_SETUP, 1, in[file]);
  /*seek to event table header*/
    fseek(in[file], S_EventTablePos(hdr[file]), SEEK_SET);
  /*read event table header*/
    fread(evt[file], packed_sizeof_TEEG, 1, in[file]);
  /*check consistency of files to be concatenated*/
    if(((S_type(hdr[file]) != S_type(output_hdr)) && (S_type(hdr[file]) != 84) && (S_type(output_hdr) != 84)) /*Scan386 contains a bug that sometimes overwrites the file type with 84*/
     ||(S_nchannels(hdr[file]) != S_nchannels(output_hdr))
     ||(S_domain(hdr[file]) != S_domain(output_hdr))
     ||(S_variance(hdr[file]) != S_variance(output_hdr))
     ||(S_rate(hdr[file]) != S_rate(output_hdr))
     ||(T_Teeg(evt[file]) != T_Teeg(output_evt)))
      {
      fprintf(stderr, "%s is incompatible with %s.\n", argv[file+1], argv[1]);
      while(file--)
	fclose(in[file]);
      exit(1);
      }
  /*update header values*/
    if(S_review(hdr[file]) == 0)
      S_review(output_hdr) = 0;
    put_S_NumEvents(output_hdr, S_NumEvents(output_hdr)+S_NumEvents(hdr[file]));
    put_S_nsweeps(output_hdr, S_nsweeps(output_hdr)+S_nsweeps(hdr[file]));
    put_S_compsweeps(output_hdr, S_compsweeps(output_hdr)+S_compsweeps(hdr[file]));
    put_S_acceptcnt(output_hdr, S_acceptcnt(output_hdr)+S_acceptcnt(hdr[file]));
    put_S_rejectcnt(output_hdr, S_rejectcnt(output_hdr)+S_rejectcnt(hdr[file]));
    put_S_NumSamples(output_hdr, S_NumSamples(output_hdr)+S_NumSamples(hdr[file]));
    put_S_EventTablePos(output_hdr, S_EventTablePos(output_hdr) + S_EventTablePos(hdr[file]) - (long)packed_sizeof_SETUP - S_nchannels(output_hdr)*(long)packed_sizeof_ELECTLOC);
    put_T_Size(output_evt, T_Size(output_evt)+T_Size(evt[file]));
    }
/*open output file*/
  if((out = fopen(argv[argc-1],
#ifdef MSDOS
    "wb"
#else
    "w"
#endif
    )) == NULL)
    {
    perror(argv[argc-1]);
    while(file--)
      fclose(in[file]);
    exit(errno);
    }
/*write output file header*/
  fwrite(output_hdr, packed_sizeof_SETUP, 1, out);
/*copy channel headers from zeroeth input file*/
  fseek(*in, (long)packed_sizeof_SETUP, SEEK_SET);
  for(file = 0; file != S_nchannels(output_hdr)*packed_sizeof_ELECTLOC; file++)
    putc(getc(*in), out);
/*copy the EEG data from each file*/
  for(file = 0; file != argc-2; file++)
    {
    printf("file1 data offset:%d\n", (long)packed_sizeof_SETUP+((long)(S_nchannels(output_hdr)))*(long)packed_sizeof_ELECTLOC); 
    fseek(in[file], (long)packed_sizeof_SETUP+((long)(S_nchannels(output_hdr)))*(long)packed_sizeof_ELECTLOC, SEEK_SET);

   	/*fread(tmpbuf, 2, 80, in[file]);
    for (i=0; i<80; i++) {
		if ((i % 31) == 0) { printf("\n"); }
    	printf("%d\n", tmpbuf[i]);
    }
    exit(-1);*/	

    for (i=0; i<80; i++) {
		if ((i % 31) == 0) { printf("\n"); }
    	printf("%d\n", (short)(256*getc(in[file])+getc(in[file])));
    }
    exit(-1);	
    file_offset_incr = S_EventTablePos(hdr[file])-(long)packed_sizeof_SETUP-((long)(S_nchannels(output_hdr)))*(long)packed_sizeof_ELECTLOC;
    while(file_offset_incr--)
      putc(getc(in[file]), out);
    }
/*write the output file event table header*/
  fwrite(output_evt, packed_sizeof_TEEG, 1, out);
/*copy the event table from each file*/
  file_offset_incr = 0L;
  for(file = 0; file != argc-2; file++)
    {
    fseek(in[file], T_Offset(evt[file])+(long)packed_sizeof_TEEG, SEEK_CUR);
    for(event = T_Size(evt[file])/(T_Teeg(evt[file])==TEEG_EVENT_TAB1? (long)packed_sizeof_EVENT1: (long)packed_sizeof_EVENT2); event != 0L; event--)
      {
      if(fread(evtbuf, (T_Teeg(evt[file])==TEEG_EVENT_TAB1? packed_sizeof_EVENT1: packed_sizeof_EVENT2), 1, in[file]) != 1)
	{
	fprintf(stderr, "Unexpected EOF in %s - expected %ld more events.\n", argv[file+1], event);
	fclose(out);
	unlink(argv[argc-1]);
	while(file != argc-2)
	  fclose(in[file++]);
	exit(1);
	}
      put_E_Offset(evtbuf, E_Offset(evtbuf)+file_offset_incr);
      fwrite(evtbuf, (T_Teeg(evt[file])==TEEG_EVENT_TAB1? packed_sizeof_EVENT1: packed_sizeof_EVENT2), 1, out);
      }
    if(getc(in[file]) != EOF)
      fprintf(stderr, "Ignoring extra bytes at end of file %s\n", argv[file+1]);
    fclose(in[file]);
    file_offset_incr += S_EventTablePos(hdr[file]) - S_nchannels(hdr[file])*packed_sizeof_ELECTLOC - packed_sizeof_SETUP;
    }
  fclose(out);
  exit(0);
  }
