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

   LLGRID.C

   Within a time range, this program produces a list of
   profile times and positions in the vicinity of latitude
   and longitude grid crossings.  The grid is specified as a
   starting position and an increment for each dimension.


                     Eric Firing
                     88-04-16

Thu  05-04-1989  Modified to print out the decimal day for
                  each range boundary and the length of the
                  range in minutes.  This requires a change
                  in the control file.

Thu  01-18-1990  Modified to print longitudes within +/- 180 (JR)

96/05/20 - EF - Modified to print a warning about missing positions, 
                but to ignore them when calculating the time ranges.

----------------------------------------------------------------

control file structure:                                         

     dbname:    (e.g. WEP)
     output: (file name)
     year_base: (e.g. 1989)
     step_size:  (number of profiles to advance)
     lat_origin:
     lat_increment:
     lon_origin:
     lon_increment:
     time_ranges:
     (list of YMDHMS time pairs:) 
        (yy/mm/dd hh:mm:ss) to (yy/mm/dd hh:mm:ss)
        .
        .
     add_time_ranges:
     skip_to:
****************************************************************/

#include <math.h>
#include "geninc.h"
#include "ioserv.h"  /* PARAMETER_LIST_ENTRY_TYPE, get_parameters(), check_error() */
#include "use_db.h"  /* check_db*() */

#define  TRUE  1
#define  FALSE 0
#define  MIN_PER_DAY 1440.0

#define  sqr(x)  (x)*(x)
#define  good_float(x)  ( (x) < ADJ_BADFLOAT )

static   int year_base;
static   FILE_NAME_TYPE dbname, out_filename, dbpath;
static   int   STEPS;
static   DOUBLE_LL_TYPE d_origin,                                                         d_increment;  /* degrees, for parameter input */

static int make_grid();

static   PARAMETER_LIST_ENTRY_TYPE parameters[] =
   {
      { " dbname:",     " %79s", dbpath,                 TYPE_STRING },
      { " output:",     " %79s", out_filename,           TYPE_STRING },
      { " year_base:",  " %d",   &year_base,             TYPE_INT    },
      { " step_size:",  " %d",   &STEPS,                 TYPE_INT    },
      { " latitude ",   NULL,    NULL,                   0           },
      { " origin:",     " %lf",  &(d_origin.lat),        TYPE_DOUBLE },
      { " increment:",  " %lf",  &(d_increment.lat),     TYPE_DOUBLE },
      { " longitude ",  NULL,    NULL,                   0           },
      { " origin:",     " %lf",  &(d_origin.lon),        TYPE_DOUBLE },
      { " increment:",  " %lf",  &(d_increment.lon),     TYPE_DOUBLE },
      { NULL,           NULL,    NULL,                   0           }
   };                   /* parameters[] */



static   OPTION_TYPE options[] =
   {
      { "end",            0          , NULL          , NULL                        },
      { "time_ranges:"  , 0          , make_grid     , NULL                        },
      { "add_time_ranges:", 1        , make_grid     , NULL                        },
      { "skip_to"       , 0          , skip_to       , NULL                        },
      { "dbname:",        TYPE_STRING, op_get_param  , dbpath                      },
      { "output:",        TYPE_STRING, op_get_param  , out_filename                },
      { "year_base:",     TYPE_INT   , op_get_param  , (char *) &year_base         },
      { "step_size:",     TYPE_INT   , op_get_param  , (char *) &STEPS             },
      { "lat_origin:",    TYPE_DOUBLE, op_get_param  , (char *) &(d_origin.lat)    },
      { "lat_increment:", TYPE_DOUBLE, op_get_param  , (char *) &(d_increment.lat) },
      { "lon_origin:",    TYPE_DOUBLE, op_get_param  , (char *) &(d_origin.lon)    },
      { "lon_increment:", TYPE_DOUBLE, op_get_param  , (char *) &(d_increment.lon) },
      { NULL,          0          , NULL,    NULL,                                 }
   };
/*
Main routine
*/
#if PROTOTYPE_ALLOWED
void do_it(FILE *fp_cnt)
#else
void do_it(fp_cnt)
FILE *fp_cnt;
#endif
{
   dbname[0] = 0;
   out_filename[0] = 0;
   year_base = 1993;
   STEPS = 1;
   d_origin.lat = 0.0;
   d_increment.lat = 1.0;
   d_origin.lon = 0.0;
   d_increment.lon = 1.0;

   while (!execute_options(fp_cnt, options, ECHO))
      ;
   fputs("\n Done.\n", stderr);

}

#if PROTOTYPE_ALLOWED
static int make_grid(FILE *fp_cnt, char *dummy, int append_flag)
#else
static int make_grid(fp_cnt, dummy, append_flag)
FILE *fp_cnt;
char *dummy;
int   append_flag;
#endif
{
   FILE *fp_out;

   int      IERR;

   YMDHMS_TIME_TYPE start, end,            /* for time range */
                    this_time, last_time;  /* previous, current profile time */
   HUN_LL_TYPE    this_position,
                  last_position;
   HUN_LL_TYPE    origin,
                  increment;          /* hundredths of a second */
   long           this_longitude,
                  last_longitude = 0L; /* longitude within +/- 180 */
   int  first_time;                   /* flag for local loop control */

   double start_day, end_day;

   /*---------- end of auto declarations for do_it -----------------*/



/***************************************************************/
   /* The following is a work-around for a Turbo-C 2.0 bug:
      it forces the math library to be linked, so fscanf
      will work with floating point arguments.
   */
   sin(0.1);
   last_position.lon = last_position.lat = 0L;

   strcpy(dbname, dbpath);
   printf("dbname: %s\n",dbname);
   check_dbopen(1, dbname, READ_ONLY, DIR_IN_MEMORY);

   if (append_flag == 1)
      fp_out = check_fopen(out_filename,"a");
   else
      fp_out = check_fopen(out_filename,"w");
   if ( fp_out == NULL )
   {
      fprintf(stderr, " ERROR: Unable to open output file %s.\n",
               out_filename);
      return (-1);
   }


   origin.lat    = to_hundredths(d_origin.lat);
   increment.lat = to_hundredths(d_increment.lat);

   origin.lon    = to_hundredths(d_origin.lon);
   increment.lon = to_hundredths(d_increment.lon);

   /* ensure that the position relative to the origin will be positive */
   origin.lon -= (360 * 360000L);
   origin.lat -=  (90 * 360000L);

/*
---> Print the header.
*/
   fprintf(fp_out, "/*  Grid boundaries for:\n");
   print_parameters(fp_out, parameters, NULL, "    ");
   fprintf(fp_out, "\n*/");
/*
---> Start the loop through time ranges listed in the control file.
*/
   while (get_time_range(fp_cnt, &start, &end) == 1)
   {
      check_dbsrch(TIME_SEARCH, (char *)&start);

      fprintf(fp_out, "\n/* ");
      print_time_range(fp_out, &start, &end);
      print_time_range(stdout, &start, &end);
      fprintf(fp_out, " */");
      first_time = TRUE;
      IERR = 0;
/*
---> Start the loop through profiles within the time range.
*/
      while (!IERR && check_time(&this_time, &start, &end))
      {
         get_hun_latlon(&this_position);
         this_longitude = this_position.lon;
         if (this_longitude != BADLONG)
         {
            if (this_longitude > 64800000L) this_longitude -= 129600000L;
            if (this_longitude > 64800000L) this_longitude -= 129600000L;
            if (first_time)
            {
               start_day = year_day(&this_time, year_base);
               fprintf(fp_out, "\n");
               write_ymdhms_time(fp_out, &this_time);
               fprintf(fp_out, "  /* %7.3f  %8.3f, %12.5f (begin time range) */",
                     to_degrees(this_position.lat),
                     to_degrees(this_longitude),
                     start_day);

               first_time = FALSE;
            }
            else     /* This is not the first profile in a time range. */
            {
               /* Has a boundary been crossed? */
               if ( ((this_position.lon - origin.lon)/increment.lon
                 !=  (last_position.lon - origin.lon)/increment.lon)
                 || ((this_position.lat - origin.lat)/increment.lat
                 !=  (last_position.lat - origin.lat)/increment.lat))
               {
                  end_day = year_day(&last_time, year_base);
                  fprintf(fp_out, "to\n");
                  write_ymdhms_time(fp_out, &last_time);
                  fprintf(fp_out, "  /* %7.3f  %8.3f, %12.5f; %4.0f min */",
                        to_degrees(last_position.lat),
                        to_degrees(last_longitude),
                        end_day, (end_day - start_day)*MIN_PER_DAY);
                  fprintf(fp_out, "\n");

                  /* find start day for NEXT segment */
                  start_day = year_day(&this_time, year_base);
                  write_ymdhms_time(fp_out, &this_time);
                  fprintf(fp_out, "  /* %7.3f  %8.3f, %12.5f */",
                        to_degrees(this_position.lat),
                        to_degrees(this_longitude),
                        start_day);
               }
            }  /* end of "not first profile" */
            last_position = this_position;
            last_longitude = this_longitude;
            last_time = this_time;
         }  /* end of "if (this_longitude != BADLONG)" */
         else
         {
            printf("\nWarning: missing position at ");
            write_ymdhms_time(stdout, &this_time);
         }
         DBMOVE(&STEPS, &IERR);   /* IERR is checked at the start of the loop */

      }  /* end of loop through profiles within a time range */

      end_day = year_day(&last_time, year_base);
      fprintf(fp_out, "to\n");
      write_ymdhms_time(fp_out, &last_time);
      fprintf(fp_out, "  /* %7.3f  %8.3f, %12.5f; %4.0f min (end time range) */",
            to_degrees(last_position.lat),
            to_degrees(last_longitude),
            end_day, (end_day - start_day)*MIN_PER_DAY);
      fprintf(fp_out, "\n\n");

   }  /* end of loop through time ranges read from control file */

   fclose(fp_out);
   DBCLOSE(&IERR);
   check_error(IERR, "DBCLOSE");
   return (1);
}

