/* %W% %E% */
#ifndef _INCLUDE_POSIX_SOURCE
#   define _INCLUDE_POSIX_SOURCE
#endif

/*
 *  include files
 */

#include <stdio.h>
#include <unistd.h>
#include <math.h>

#include "RINEX.h"

/*
 *  function prototypes
 */

int FindRINEXEndOfHeader( FILE * );
int GetLastRINEXEpoch( FILE *, int, char **, struct RINEX_obs * );
int GetNextRINEXEpoch( FILE *, int, char **, struct RINEX_obs * );
int ReadRINEXObsTypes( FILE *, int *, char ** );
int main( int, char ** );
int tchkeps( long, double, long, double, double );
void mjdyd( long, double, long, double );

/*
 *  global definitions and variables
 */

#define FILENAME_LENGTH      65
#define vrsn         "0503.30"

static char *sccsid= "%W% %E%";

int main( int argc, char *argv[] )
/********1*********2*********3*********4*********5*********6*********7*********
 * name:            bei
 * version:         0503.30
 * written by:      M. Schenewerk
 * purpose:         find begin, end and interval of data in RINEX files
 *
 * input parameters
 * ----------------
 *
 * output parameters
 * -----------------
 *
 *
 * local variables and constants
 * -----------------------------
 *
 * global variables and constants
 * ------------------------------
 *
 *
 * called by:       
 *
 * calls:           
 *
 * include files:   
 *
 * references:      
 *
 * comments:        
 *
 * see also:        
 *
 ********1*********2*********3*********4*********5*********6*********7*********
 *:modification history
 *:9612.15, MSS, Creation
 *:9905.12, MSS, Keep only the largest data interval.
 *:              Force secondary max/min to match the interval value.
 *:9906.01, MSS, When searching for min times and data spans two days,
 *:              update/pass integer day from fractional to integer.
 *:0202.14, MSS, Change the way the "next to" min and max are identified
 *:              and stored to eliminate a round-off problem.
 *:0503.30, MSS, Added code to "round" to the longest interval when comparing
 *:              files with different data intervals.
 ********1*********2*********3*********4*********5*********6*********7*********/
{
   char afile[FILENAME_LENGTH];
   char *list[TYPE_MAX];
   char *pgm;

   double interval= (double)1 / (double)86400;
   double round= (double)0.499999 / (double)86400;
   double t1maxl= (double)0;
   double t2maxl= (double)0;
   double t1minl= (double)0;
   double t2minl= (double)0;
   double tmaxl;
   double tminl;
   double tmp_interval;

   int allflg= 1;
   int bflg= 0;
   int c;
   int eflg= 0;
   int errflg= 0;
   int i;
   int j;
   int iflg= 0;
   int ios;
   int nlist;
   int sflg= 0;

   long t1maxh= -1L;
   long t2maxh= -1L;
   long t1minh= 100000L;
   long t2minh= 100000L;
   long tmaxh;
   long tminh;

   FILE *pfile= NULL;

   struct RINEX_obs obs;

   extern char *optarg;
   extern int optind;
   extern int optopt;
/*
 *   0.0  parse command line
 */
   pgm= argv[0];

   while ((c = getopt(argc, argv, "2bei")) != -1)
      switch (c) {
      case '2':
         sflg++;
         break;
      case 'b':
         bflg++;
         allflg= 0;
         break;
      case 'e':
         eflg++;
         allflg= 0;
         break;
      case 'i':
         iflg++;
         allflg= 0;
         break;
      case '?':
         fprintf(stderr, "%s ERROR: Unrecognized option: - %c\n",
                 pgm, optopt);
         errflg++;
      }
   if(errflg || optind == argc ) {
      fprintf(stderr, "%s(%s) USAGE: %s {-bei} file(s)\n",
              pgm, vrsn, pgm);
      exit(1);
   }
/*
 *  1.0  loop over all files
 */
   for( i= optind; i < argc; i++ ) {
      strcpy( afile, argv[i] );
      if( (pfile= fopen( afile, "r" )) == NULL ) {
         fprintf( stderr, "%s ERROR: opening \"%s\"\n",
                  pgm, afile );
         exit(2);
      }
/*
 *  2.0  scan header and get obs types
 */
      if( (ios= ReadRINEXObsTypes( pfile, &nlist, list )) != 0 ) {
         fprintf( stderr, "%s ERROR: Reading obs types from \"%s\"\n",
                  pgm, afile );
         exit(3);
      }

      if( (ios= FindRINEXEndOfHeader( pfile )) != 0 ) {
         fprintf( stderr, "%s ERROR: Reading header from \"%s\"\n",
                  pgm, afile );
         exit(3);
      }
/*
 *  3.0  read first epoch; set min; initialize variables for search
 */
      if( (ios= GetNextRINEXEpoch( pfile, nlist, list, &obs )) != 0 ) {
         fprintf( stderr, "%s ERROR: Reading first epoch from \"%s\"\n",
                  pgm, afile );
         exit(4);
      }

      tminh= obs.mjd;
      tminl= obs.day;

      tmaxh= obs.mjd;
      tmaxl= obs.day;
/*
 *  4.0  read second epoch to set interval
 */
      if( (ios= GetNextRINEXEpoch( pfile, nlist, list, &obs )) != 0 ) {
         fprintf( stderr, "%s ERROR: Reading second epoch from \"%s\"\n",
                  pgm, afile );
         exit(4);
      }
      tmp_interval= (double)(obs.mjd - tminh) + (obs.day - tminl);

      tmaxh= obs.mjd;
      tmaxl= obs.day;
/*
 *  5.0  read last epoch
 */
      fseek( pfile, 0L, SEEK_END );
      if( (ios= GetLastRINEXEpoch( pfile, nlist, list, &obs )) != 0 ) {
         fprintf( stderr, "%s ERROR: Reading last epoch from \"%s\"\n",
                  pgm, afile );
         exit(4);
      }

      tmaxh= obs.mjd;
      tmaxl= obs.day;

      fclose( pfile );
/*
 *  6.0  test for primary and secondary max/min
 */
      if( tmp_interval > interval ) {
         interval= tmp_interval;
         t1minl = ceil (t1minl / interval) * interval;
         t2minl = ceil (t2minl / interval) * interval;
         t1maxl = floor (t1maxl / interval) * interval;
         t2maxl = floor (t2maxl / interval) * interval;
      }

      if( tchkeps( tmaxh, tmaxl, t1maxh, t1maxl, round ) >= 0 ) {
         t2maxh= t1maxh;
         t2maxl= t1maxl;
         t1maxh= tmaxh;
         t1maxl = floor (tmaxl / interval) * interval;
      } else if( tchkeps( tmaxh, tmaxl, t2maxh, t2maxl, round ) > 0 ) {
         t2maxh= tmaxh;
         t2maxl = floor (tmaxl / interval) * interval;
      }

      if( tchkeps( tminh, tminl, t1minh, t1minl, round ) <= 0 ) {
         t2minh= t1minh;
         t2minl= t1minl;
         t1minh= tminh;
         t1minl = ceil (tminl / interval) * interval;
      } else if( tchkeps( tminh, tminl, t2minh, t2minl, round ) < 0 ) {
         t2minh= tminh;
         t2minl = ceil (tminl / interval) * interval;
      }
   }
/*
 *  7.0  output result
 */
   if( argc-optind > 1 && sflg ) {
      tmaxh= t2maxh;
      tmaxl= t2maxl;
      tminh= t2minh;
      tminl= t2minl;
   } else {
      tmaxh= t1maxh;
      tmaxl= t1maxl;
      tminh= t1minh;
      tminl= t1minl;
   }

   if( allflg || bflg )
      printf( "%.8lf ", (double)tminh + tminl );

   if( allflg || eflg )
      printf( "%.8lf ", (double)tmaxh + tmaxl );

   if( allflg || bflg )
      printf( "%.3lf", (double)86400*interval );

   putchar( '\n' );

   exit( 0 );
}
