/*

gcc -O -o asc2mseed_mc asc2mseed_mc.c -I./qlib2-2011.046 -L./qlib2-2011.046 -lqlib2-64.debug -lm

*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/param.h>
#include <fcntl.h>    
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <utime.h>

#include "qlib2.h"

/* globale Arbeitsvariablen */

#define BLKSZ 4096

#include "cube.h"



long leapsecond_times[NOLS][2];
/* from [0] to [1] */

void ini_leapseconds()
{
long i,sec;   
struct tm ts;   

	for ( i = 0; i<NOLS; i++ )
	{
		leapsecond_times[i][0]=0;
		leapsecond_times[i][1]=9999999999;
	}

	for ( i = 0; i<NOLS; i++ )
	{
		ts.tm_year=leapsecond_dates[i][0]-1900;
		ts.tm_mon=leapsecond_dates[i][1]-1;
		ts.tm_mday=leapsecond_dates[i][2];
  		ts.tm_hour=leapsecond_dates[i][3]; 
  		ts.tm_min=leapsecond_dates[i][4];
		ts.tm_sec=leapsecond_dates[i][5];
 		sec = mktime(&ts);			
		leapsecond_times[i][0]=sec+leapsecond_dates[i][6];
		if (i>0) leapsecond_times[i-1][1]=sec+leapsecond_dates[i][6];
	}
}


long utc_from_gps(long gps_seconds)
{

	long val,i;
	val=0;
	for ( i = 0; i<NOLS; i++ ) if ((gps_seconds > leapsecond_times[i][0]) && (gps_seconds <= leapsecond_times[i][1])) {val=gps_seconds-leapsecond_dates[i][6]-1;}
        return val;
}


int write_mseed_file (FILE *fout, int *data, long nsamp, char *station_id, int chan, int s_rate, long sec, int msec, int verbose);


void main(argc,argv)
int argc;
char **argv;
{
  FILE 			*fmseed;
  int			ch;
  long			j;
  int			*data,**alldata;
  int			start_hour,start_day,test_hour,test_day,ampx1[100],test_val,start_val;
  char                  help[100],help2[100],helpa[10][100],helpb[10][100];
  long			iii,jjj,sec,sec_ut,mksec,dt;

  char  		buf[1000],codex;
  int			code,jx,verbose,split;

  char 			station_name[1024],stationid[10];
extern char *optarg;
extern int optind, opterr, optopt;
   int c,errflg; 

  errflg=0;
  verbose = 0;            
  split=0;  /* hourly split */

  time_t t,start_time,test_time;
  struct tm *tss,tss_test;

   opterr=0; while ((c = getopt (argc, argv, "o:vd")) != -1)
   switch (c)
       {
          case 'v':        /* verbose */
	    verbose = 1;            
	    break;
          case 'd':        /* daily split */
	    split=1;            
	    break;
          case '?':
            fprintf(stderr,"%s ERROR: Unrecognized option: -%c\n", argv[0], optopt);
            errflg++;
        }

    if (errflg) {
        fprintf(stderr, "%s ERROR: usage - asc2mseed_mc -v verbose -d (for daily split files)\n", argv[0]);
        exit(2);
    }

   putenv ("TZ=GMT");
   tzset; 
   ini_leapseconds();

  if (!(data    = malloc (MXSMP * sizeof(int))))   { fprintf(stderr, "%s ERROR: malloc for data    failed, not enough core memory\n",argv[0]); exit(0); }

/* read config file */

   if (fgets(buf,1000,stdin)) 
   {
	code=sscanf(buf,STR_FORMAT,(char *) SC_STR);
   }




/* allocating arrays for the CH_NUM time series */
  if (!(alldata = malloc (CH_NUM * sizeof(int)))) { fprintf(stderr, "%s ERROR: malloc failed, not enough core memory\n",argv[0]); exit(0); }
  for (ch = 0; ch < CH_NUM; ch++) if (!(alldata[ch] = malloc (MXSMP * sizeof(int)))) { fprintf(stderr, "%s ERROR: malloc failed, not enough core memory\n",argv[0]); exit(0); }



/* read til first second */

  dt=-1;
  while ( dt != 0)
  {
       if (fgets(buf,1000,stdin))
       {
	switch (CH_NUM)
	{
		case 1: code=sscanf(buf,"%ld%ld%d",&sec_ut,&mksec,&ampx1[0]); break;
		case 2: code=sscanf(buf,"%ld%ld%d%d",&sec_ut,&mksec,&ampx1[0],&ampx1[1]); break;
		case 3: code=sscanf(buf,"%ld%ld%d%d%d",&sec_ut,&mksec,&ampx1[0],&ampx1[1],&ampx1[2]); break;
	}
/* no data treatment */
	if (sec_ut==-1)
	{ 
		fprintf(stderr,"ERROR: No useful data in asc2mseed!\n"); 
		exit(77);
	}
       }
       dt=mksec;
  }
  sec=utc_from_gps(sec_ut);
  t=(long) (sec);

/*  fprintf(stderr,"YYY %s", ctime(&t)); */

/* main loop */

  j=0;
  for (ch=0; ch<CH_NUM; ch++) alldata[ch][j]=ampx1[ch];
  start_time=sec;
  tss = localtime(&start_time); 
  start_hour = (int) (tss->tm_hour);
  start_day  = (int) (tss->tm_mday);
/*  fprintf(stderr,"%d \n",start_hour); */


  memcpy(&tss_test, localtime(&start_time), sizeof(struct tm)); 
  jjj=mktime(&tss_test);

  sprintf(stationid, "c0%3s", DEV_NO);


/* fprintf(stderr,"%s \n",stationid); */

  strftime(help2, 80, "%y%m%d%H%M%S", &tss_test);
  for (ch=0; ch<CH_NUM; ch++) 
  {
  	sprintf(helpa[ch], "ex%3s%12s.pri%1d", DEV_NO,help2,ch);
  	sprintf(helpb[ch], "ex%3s%12s.pri%1d", DEV_NO,help2,ch);
  }
  while (!feof(stdin))
  {
	if (j==0) 
	{

		strftime(help, 80, "%y%m%d%H%M%S", &tss_test); 
  		for (ch=0; ch<CH_NUM; ch++) sprintf(helpa[ch], "ex%3s%12s.pri%1d", DEV_NO,help,ch);
		iii=mktime(&tss_test);
	}
	j++;

	if (fgets(buf,100,stdin))
	{
		switch (CH_NUM)
		{
			case 1: code=sscanf(buf,"%ld%ld%d",&sec_ut,&mksec,&ampx1[0]); break;		
			case 2: code=sscanf(buf,"%ld%ld%d%d",&sec_ut,&mksec,&ampx1[0],&ampx1[1]); break;
			case 3: code=sscanf(buf,"%ld%ld%d%d%d",&sec_ut,&mksec,&ampx1[0],&ampx1[1],&ampx1[2]); break;
		}
	}
	for (ch=0; ch<CH_NUM; ch++) alldata[ch][j]=ampx1[ch];  

	sec=utc_from_gps(sec_ut);
	test_time=sec;

  	memcpy(&tss_test, localtime(&test_time), sizeof(struct tm));
 	test_day  = (int) (tss_test.tm_mday); 
 	test_hour = (int) (tss_test.tm_hour); 
	test_val  = test_hour;
	start_val = start_hour;
/* check if daily or hourly split */
	if ( split == 1 ) 
	{
		test_val  = test_day;
		start_val = start_day;
	}


	if ( test_val != start_val )
	{ 

/*		fprintf(stderr,"i convert from 0 to %d file=%s startime = %ld\n",j-1,helpa,iii); */

		for (ch=0; ch<CH_NUM; ch++)
		{

/* fprintf(stderr, "writing mseed file ch=%d f=%s with n=%d samples\n", ch, helpa[ch],j); */
			if (j>0) if (!(fmseed=fopen(helpa[ch], "wb"))) { fprintf(stderr, "ERROR: could not open mseed file %s\n", helpa[ch]); exit;}
		
/*			sprintf(station_name, "%s", "oc01"); */
			for (jx=0; jx<j; jx++) data[jx]=alldata[ch][jx];
			if (j>0) if (!(write_mseed_file (fmseed, data, j, DEV_NO, ch, S_RATE, iii, 0, verbose))) { fprintf(stderr, "ERROR: problems writing mseed file %s\n", helpa[ch]); exit;} 
			if (verbose==1) fprintf(stderr,"file: %s samples: %ld\n",helpa[ch],j);

			if (j>0) fclose(fmseed);

			start_hour=test_hour;
			start_day=test_day;
			alldata[ch][0]=ampx1[ch];
/*			j=0;		*/
			strftime(help2, 80, "%y%m%d%H%M%S", &tss_test);		
			sprintf(helpb[ch], "ex%3s%12s.pri%1d", DEV_NO,help2,ch);

  			jjj=mktime(&tss_test);
		}
		j=0;		
	}
  }

  j=j-1;


/* ------------------------------ */
  for (ch=0; ch<CH_NUM; ch++)
  {
		if (j>0) if (!(fmseed=fopen(helpb[ch], "wb")))
		{
			fprintf(stderr, "ERROR: could not open mseed file %s\n", helpb[ch]);
			exit;
		}
		
/*		sprintf(station_name, "%s", "oc01"); */
		for (jx=0; jx<j; jx++) data[jx]=alldata[ch][jx];
		if (j>0) if (!(write_mseed_file (fmseed, data, j, DEV_NO, ch, S_RATE, jjj, 0, verbose)))
		{
			fprintf(stderr, "ERROR: problems writing mseed file %s\n", helpb[ch]);
			exit;
		}
		if (verbose==1) fprintf(stderr,"file: %s samples: %ld\n",helpb[ch],j);

		
		if (j>0) fclose(fmseed);
  }


 }

/* ------------------------------------------------------ */
int write_mseed_file (FILE *fout, int *data, long nsamp, char *station_id, int chan, int s_rate, long sec, int msec, int verbose)
{
	DATA_HDR *out_hdr;			/* output mseed header */
	char *pp_ms=NULL;				/* pointer to output mseed */
	int n;
	int n_blocks;				/* returned number of blocks written */
	int status;
	int nleft;				/* numbers */
	char *p;				
	struct tm *t, tt;

  	int    format=-1;
	
/* fprintf(stderr,"----- %d %ld %s %d %d %ld %ld\n",data[0],nsamp,station_id,chan,s_rate,sec,msec);	*/
	t = localtime(&sec);
	memcpy (&tt, t, sizeof(struct tm));
	
	
/* allocations */
	if (!(out_hdr = malloc (sizeof(DATA_HDR))))
	{
		if (verbose) fprintf (stderr, "write_mseed_file malloc failed\n");
		exit(0);
	}

/* init of the header */
	init_data_hdr (out_hdr);

/* setting part of the header */
	out_hdr->begtime=add_time(int_time_from_time_tm(&tt),0, msec*1000);
	out_hdr->hdrtime=add_time(out_hdr->begtime, 0, 0);
	out_hdr->blksize=BLKSZ;
	strcpy(out_hdr->station_id, station_id);
	sprintf(out_hdr->location_id, "XX");
	sprintf(out_hdr->channel_id, "p%d", chan);
	sprintf(out_hdr->network_id, "XX"); 
	out_hdr->sample_rate = s_rate;
	out_hdr->sample_rate_mult = 1;
	out_hdr->seq_no = 0;
        out_hdr->record_type = 'D';
        out_hdr->num_ticks_correction = 0;
  	out_hdr->data_type = STEIM1;
	out_hdr->num_samples = nsamp;

	out_hdr->hdr_wordorder = set_hdr_wordorder (SEED_LITTLE_ENDIAN); 
        out_hdr->data_wordorder = set_data_wordorder(SEED_LITTLE_ENDIAN);

	if (verbose==1) fprintf(stderr, "station: %s chan: %s stime: %s",
						out_hdr->station_id,
						out_hdr->channel_id,
						time_to_str(out_hdr->begtime, MONTH_FMT_1));

/* pack mseed_data */

	if (verbose==1) fprintf(stderr, " . ");
	pp_ms=NULL;
	status = ms_pack_data (out_hdr, NULL, nsamp, (int *)data, &n_blocks, &pp_ms, 0, NULL);
	if (status != nsamp) 
	{
		fprintf(stderr, "problems packing mseed_file \n");
		exit(0);
	}
		

/* write mseed file */

	if (verbose==1) fprintf(stderr, ". ");
	n=nleft=n_blocks;
	p=(char *)pp_ms;
	while (nleft>0 && n>0)
	{
		n= fwrite (p, out_hdr->blksize, nleft, fout);
		p+=n*out_hdr->blksize;
		nleft-=n;
	}
	free(pp_ms);
	if (nleft)
	{
		fprintf(stderr, "problems writing all blocks (nleft: %d)\n", nleft);
	}

	free(out_hdr); 

	return (1);
}	





