/***************************************************************

ARRDEP (ARRiveDEPart)

This program is derived from TIMSLIP.  Its purpose is to
generate a file of time ranges centered on station arrival
and departure times, for use in comparing on-station to
off-station profiles.

Wed  01-04-1989
Eric Firing

Fri  07-21-1989  EF
   added the "whole_station" and "whole_underway" to the list
   of range options.

95/05/22  EF
   Increased NRMAX from 21 to 1001, and added error checking for n_refs
   exceeding NRMAX.

CONTROL FILE STRUCTURE:

      reference_file:
      output_file:

      year_base=            { year base for decimal day calculations }

                             { The jump in velocity will be
                             between indices (n_refs-1)/2
                             and (n_refs-1)/2 +1.  For
                             example, it will be between 6
                             and 7 if n_refs is 13.  Note
                             that all these indices start
                             from 0, C-style, not from 1.
                             However, the lowest index
                             specified must be >= 1, since
                             the time of the start of
                             ensemble 1 is (approximately)
                             the time recorded with ensemble
                             0.}

      n_refs=

      i_ref_l0=              { first and last indices of ensembles used }
      i_ref_l1=
      i_ref_r0=              { "l" is before jump, "r" is after }
      i_ref_r1=              { minimum is 1, not zero }

      range:                 { underway, on_station, or all; all gives
                               the complete interval around the jump,
                               from l0 to r1; underway and on_station
                               give only the l0 to l1 or r0 to r1 interval
                               during which the ship is underway or on
                               station}
                             { whole_underway or whole_station: give
                               the entire intervals when ship was
                               underway or on station }

      up_thresh=             { m/s, for jump detection }
      down_thresh=

      margin=    10          { seconds to subtract from first time, add to
                               second, to allow for rounding errors and ensure
                               that the time range brackets the ensemble
                               times. }


*/

#include "common.h"
#include "dbext.h"   /* YMDHMS_TIME_TYPE, ADJ_BADFLOAT */
#include "use_db.h"  /*  write_ymdhms_time() */
#include "ioserv.h"
#include "time_.h"   /* yd_to_ymdhms_time() */
#include "cal.h"     /* VELOCITY_TYPE, read_ref() */

#define   NRMAX 1001
#define   R_ALL            0
#define   R_ON_STATION     1
#define   R_UNDERWAY       2
#define   R_WHOLE_STATION  3
#define   R_WHOLE_UNDERWAY 4

/*--------------------------------------------------------------
   Global variables for this module:
*/

FILE *fp_ref, *fp_out;
VELOCITY_TYPE refs[NRMAX];
int n_refs;
static int year_base;
double up_thresh, down_thresh;

/* ref indices of left, right ranges for calib: */
static int i_ref_l0, i_ref_l1, i_ref_r0, i_ref_r1;

static double margin;

/* Functions: */
#if PROTOTYPE_ALLOWED
int get_ref(FILE *fp_ref, VELOCITY_TYPE refs[], int n_refs);
int is_jump(VELOCITY_TYPE refs[], int n_refs, double up_thresh, double down_thresh);
#else
int get_ref();
int is_jump();
#endif

/*============================================================*/

#if PROTOTYPE_ALLOWED
void do_it(FILE *fp_cnt)
#else
void do_it(fp_cnt)
FILE *fp_cnt;
#endif
{
   int finished = 0;
   int open = 0;      /* used only for "whole" intervals */
   int i, i0, i1;
   int jump_dir;     /* 1 is up, -1 is down in speed */

   double speed;
   YMDHMS_TIME_TYPE start, end;
   double epsilon;      /* time margin in days */

   static FILE_NAME_TYPE ref_filename, out_filename;
   static int i_range;

   static NAME_LIST_ENTRY_TYPE range_names[]=
   {
      {"all",           R_ALL},
      {"on_station",    R_ON_STATION},
      {"underway",      R_UNDERWAY},
      {"whole_station", R_WHOLE_STATION},
      {"whole_underway",R_WHOLE_UNDERWAY},
      {NULL,            0}
   };

   /*------------------------------------------------------*/

   static NAME_LIST_TYPE name_lists[]=
   {
      {range_names}
   };


   static PARAMETER_LIST_ENTRY_TYPE parameters[] =
   {
      {" reference_file:",  " %79s",  ref_filename,  TYPE_STRING},
      {" output_file:",     " %79s",  out_filename,  TYPE_STRING},
      {" year_base=",       " %d",    &year_base,    TYPE_INT},
      {" n_refs=",          " %d",    &n_refs,       TYPE_INT},
      {" i_ref_l0=",        " %d",    &i_ref_l0,     TYPE_INT},
      {" i_ref_l1=",        " %d",    &i_ref_l1,     TYPE_INT},
      {" i_ref_r0=",        " %d",    &i_ref_r0,     TYPE_INT},
      {" i_ref_r1=",        " %d",    &i_ref_r1,     TYPE_INT},
      {" range:",           " %s",    &i_range,      TYPE_TRANS},
      {" up_thresh=",       " %lf",   &up_thresh,    TYPE_DOUBLE},
      {" down_thresh=",     " %lf",   &down_thresh,  TYPE_DOUBLE},
      {" margin=",          " %lf",   &margin,       TYPE_DOUBLE},
      { NULL,              NULL,    NULL,          0           }
   };                   /* parameters[] */

   if(get_parameters(fp_cnt, parameters, name_lists))  exit(-1);
   epsilon = margin / SECONDS_PER_DAY;

   if (i_ref_l0 < 0 || i_ref_l1 < i_ref_l0 ||
                       i_ref_r0 < i_ref_l1 || i_ref_r1 < i_ref_r0
                     || n_refs <= i_ref_r1 
                     || n_refs > NRMAX )
   {
      printf("\nError in i_ref indices; minimum value is 0, max is n_refs-1, \n");
      printf("\n  they must increase.  Also, n_refs cannot exceed %d\n", NRMAX);
      exit(-1);
   }

   if (i_range == R_ALL)
   {
      i0 = i_ref_l0;
      i1 = i_ref_r1;
   }
   else if (i_range == R_WHOLE_UNDERWAY || i_range == R_WHOLE_STATION)
   {
      i0 = i_ref_r0;
      i1 = i_ref_l1;
   }

   fp_ref = check_fopen(ref_filename, "r");
   fp_out = check_fopen(out_filename, "w");

   fprintf(fp_out, "/*");
   print_parameters(fp_out, parameters, name_lists, "\n");
   fprintf(fp_out, "*/\n");

   /* initialize by filling the refs array */
   for (i=0; i<n_refs && !finished; i++)
      finished = get_ref(fp_ref, refs, n_refs);

   /* If we want whole ranges, the first may start here. */
   speed = sqrt(sqr(refs[0].u) + sqr(refs[0].v));
   if (   (i_range == R_WHOLE_UNDERWAY && speed > up_thresh)
       || (i_range == R_WHOLE_STATION  && speed < down_thresh))
   {
      yd_to_ymdhms_time(refs[0].t - epsilon, year_base, &start);
      write_ymdhms_time(fp_out, &start);
      fprintf(fp_out, " /* %11.6f */ to  ", refs[i0].t);
      open = 1;
   }

   while (!finished)
   {
      if (!finished && (jump_dir = is_jump(refs, n_refs, up_thresh, down_thresh)) != 0)
      {
         if (i_range == R_UNDERWAY || i_range == R_ON_STATION)
         {
            if (   (i_range == R_UNDERWAY && jump_dir == JUMP_UP)
                || (i_range == R_ON_STATION && jump_dir == JUMP_DOWN))
            {
               i0 = i_ref_r0;
               i1 = i_ref_r1;
            }
            else
            {
               i0 = i_ref_l0;
               i1 = i_ref_l1;
            }
         }

         yd_to_ymdhms_time(refs[i0].t - epsilon, year_base, &start);
         yd_to_ymdhms_time(refs[i1].t + epsilon, year_base, &end);

         if (  (i_range == R_WHOLE_UNDERWAY && jump_dir == JUMP_UP)
             ||(i_range == R_WHOLE_STATION  && jump_dir == JUMP_DOWN))
         {
            write_ymdhms_time(fp_out, &start);
            fprintf(fp_out, " /* %11.6f */  to  ", refs[i0].t);
            open = 1;
         }
         else if (  (i_range == R_WHOLE_STATION  && jump_dir == JUMP_UP)
                  ||(i_range == R_WHOLE_UNDERWAY && jump_dir == JUMP_DOWN))
         {
            write_ymdhms_time(fp_out, &end);
            fprintf(fp_out, " /* %11.6f */\n", refs[i1].t);
            open = 0;
         }
         else
         {
            write_ymdhms_time(fp_out, &start);
            fprintf(fp_out, "  to  ");
            write_ymdhms_time(fp_out, &end);
            fprintf(fp_out, "  /*  %10.5f to  %10.5f;  %4.0f s, %s */\n",
                        refs[i0].t, refs[i1].t,
                        (refs[i1].t - refs[i0].t) * SECONDS_PER_DAY,
                        jump_dir == JUMP_UP ? "depart" : "arrive" );
         }
      }
      finished = get_ref(fp_ref, refs, n_refs);
   }  /* finished */
   if (open == 1)   /* close the "whole" interval */
   {
      yd_to_ymdhms_time(refs[n_refs-1].t + epsilon, year_base, &end);
      write_ymdhms_time(fp_out, &end);
      fprintf(fp_out, " /* %11.6f */\n", refs[i1].t);
   }

   fclose(fp_ref);
   fclose(fp_out);
}                       /* do_it() */

