/*******************************************************************************
      
    FILE:  load_bot.c
    USAGE: load_bot <control-file>

    This program loads CTD bottle samples data into a CODAS database.

*/
#include "geninc.h"
#include "use_db.h"
#include "ioserv.h"       /* error_found(), check_error() */
#include "data_id.h"

#define MISSING -99.0
#define PO4      16       /* variable IDs not in data_id.h */
#define NO3      17
#define NO2      18
#define SiO2     19

typedef struct
{
   CHAR   ship_name[12];
   CHAR   cruise_id[12];
   CHAR   unused[24];
} CONFIGURATION_1_TYPE;

typedef struct
{
   USHORT station;
   USHORT num_bottles;
   USHORT max_depth;
   CHAR   unused[18];
} ANCILLARY_1_TYPE;

struct
{
   DMSH_POSITION_TYPE lon;
   DMSH_POSITION_TYPE lat;
} pos;

DEPTH_RANGE_TYPE depth_range;
CONFIGURATION_1_TYPE conf;
ANCILLARY_1_TYPE anc;
YMDHMS_TIME_TYPE time;
FLOAT *pressure, *depth, *temp, *salinity, *pot_temp, *oxygen, *po4, *no3, *no2, *sio2;
FILE_NAME_TYPE dbname, prdname, ascname;

#if PROTOTYPE_ALLOWED
int get_header(FILE *fp);
int get_data(FILE *fp);
int alloc_arrays(void);
#else
int get_header();
int get_data();
int alloc_arrays();
#endif

#if PROTOTYPE_ALLOWED
void do_it(FILE *fpcnt)
#else
void do_it(fpcnt)
FILE *fpcnt;
#endif
{
   int dbid = 1, memmode = 0, ierr = 0, nprf = 0, type;
   unsigned int n, nbad;
   FILE *fpasc;

   static PARAMETER_LIST_ENTRY_TYPE ctdcnt[] =
   {
      " DATABASE_NAME:"    , " %79s", dbname              , TYPE_STRING,
      " DEFINITION_FILE:"  , " %79s", prdname             , TYPE_STRING,
      " SHIP_NAME:"        , " %11s", conf.ship_name      , TYPE_STRING,
      " CRUISE_ID:"        , " %11s", conf.cruise_id      , TYPE_STRING,
      " ASCII_FILE:"       , " %79s", ascname             , TYPE_STRING,
      NULL                 , NULL   , NULL                , 0
   }; 

   if (get_parameters(fpcnt, ctdcnt, NULL)) return;
   dbname[79] = prdname[79] = ascname[79] = '\0';
   print_parameters(stdout, ctdcnt, NULL, "\n");
   check_error( ((fpasc = fopen(ascname, "rt")) == NULL), "opening ASCII file");

   DBCREATE(&dbid, dbname, prdname, &memmode, &ierr);
   if (DBERROR(&ierr, "creating database")) return;

   DBNEWBLK(&ierr);
   if (DBERROR(&ierr, "creating block")) goto close_db;

   type = CONFIGURATION_1;
   n = sizeof(CONFIGURATION_1_TYPE);
   DBADD(&type, (char *) &conf, &n, &ierr);
   if (DBERROR(&ierr, "adding configuration")) goto close_db;

   while (get_header(fpasc) == 0)
   {
      if (nprf > OPTIMUM_PROFILES_PER_BLOCK)
      {
         DBENDBLK(&ierr);
         if (DBERROR(&ierr, "closing block")) goto close_db;
         DBNEWBLK(&ierr);
         if (DBERROR(&ierr, "creating block")) goto close_db;
         nprf = 0;
         type = CONFIGURATION_1;
         n = sizeof(CONFIGURATION_1_TYPE);
         DBADD(&type, (char *) &conf, &n, &ierr);
         if (DBERROR(&ierr, "adding configuration")) goto close_db;
      }

      if (error_found( get_data(fpasc), "reading data from ASCII file"))
         goto close_db;

      DBNEWPRF(&time, &ierr);
      if (DBERROR(&ierr, "creating profile")) goto close_db;
      nprf++;
      printf("\n...Profile: %d ==> ", nprf);
      print_ymdhms_time(stdout, &time);

      type = POSITION;
      n = sizeof(pos);
      DBADD(&type, (char *) &pos, &n, &ierr);
      if (DBERROR(&ierr, "adding position")) goto close_db;

      type = DEPTH_RANGE;
      n = sizeof(DEPTH_RANGE);
      DBADD(&type, (char *) &depth_range, &n, &ierr);
      if (DBERROR(&ierr, "adding depth range")) goto close_db;

      type = P;
      n = sizeof(FLOAT) * anc.num_bottles;
      DBADD(&type, (char *) pressure, &n, &ierr);
      if (DBERROR(&ierr, "adding pressure")) goto close_db;

      type = DEPTH;
      n = anc.num_bottles;
      DBADD_F(&type, depth, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding depth")) goto close_db;
      if (error_found( (nbad != 0), "scaling depth")) goto close_db;

      type = TEMPERATURE;
      DBADD_F(&type, temp, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding temperature")) goto close_db;
      if (error_found( (nbad != 0), "scaling temperature")) goto close_db;

      type = SALINITY;
      DBADD_F(&type, salinity, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding salinity")) goto close_db;
      if (error_found( (nbad != 0), "scaling salinity")) goto close_db;

      type = POTENTIAL_TEMP;
      DBADD_F(&type, pot_temp, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding potential temperature")) goto close_db;
      if (error_found( (nbad != 0), "scaling potential temperature")) goto close_db;

      type = OXYGEN;
      DBADD_F(&type, oxygen, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding oxygen")) goto close_db;
      if (error_found( (nbad != 0), "scaling oxygen")) goto close_db;

      type = PO4;
      DBADD_F(&type, po4, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding PO4")) goto close_db;
      if (error_found( (nbad != 0), "scaling PO4")) goto close_db;

      type = NO3;
      DBADD_F(&type, no3, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding NO3")) goto close_db;
      if (error_found( (nbad != 0), "scaling NO3")) goto close_db;

      type = NO2;
      DBADD_F(&type, no2, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding NO2")) goto close_db;
      if (error_found( (nbad != 0), "scaling NO2")) goto close_db;

      type = SiO2;
      DBADD_F(&type, sio2, &n, &nbad, &ierr);
      if (DBERROR(&ierr, "adding SiO2")) goto close_db;
      if (error_found( (nbad != 0), "scaling SiO2")) goto close_db;

      type = ANCILLARY_1;
      n = sizeof(ANCILLARY_1_TYPE);
      DBADD(&type, (char *) &anc, &n, &ierr);
      if (DBERROR(&ierr, "adding ancillary")) goto close_db;

      free(pressure); free(depth); free(temp); free(salinity); free(pot_temp);
      free(oxygen); free(po4); free(no3); free(no2); free(sio2);

      DBENDPRF(&ierr);
      if (DBERROR(&ierr, "closing profile")) goto close_db;
   }

   close_db:
      DBENDBLK(&ierr);
      DBERROR(&ierr, "closing block");
      DBCLOSE(&ierr);
      DBERROR(&ierr, "closing database");
      printf("\n\n DATABASE CLOSED SUCCESSFULLY\n\n");
}

#if PROTOTYPE_ALLOWED
int get_header(FILE *fp)
#else
int get_header(fp)
FILE *fp;
#endif
{
   int n, hhmm;
   float rlat, rlon;
   long llat, llon;

   n = fscanf(fp, " %hu %hu %f %f %hd %hd %hd %d %hu",
      &(anc.station), &(anc.num_bottles), &rlat, &rlon,
      &(time.month), &(time.day), &(time.year), &hhmm, &(anc.max_depth));
   switch(n)
   {
      case 9:
         time.year = yr4digit(time.year);
         time.hour = (SHORT) (hhmm / 100);
         time.minute = hhmm % 100;
         time.second = 0;
         llat = rlat * 360000L;  /* from decimal degrees to hundredths of sec */
         llon = rlon * 360000L;
         HUNPOS(&(pos.lon), &llon); /* from hundredths of sec to DMSH position */
         HUNPOS(&(pos.lat), &llat);
         return(0);
      case EOF:
         printf("\n END of ASCII file");
         return(EOF);
      default:
         printf("\n ERROR: Scanning ASCII file for header");
         return(1);
   }
}

#if PROTOTYPE_ALLOWED
int get_data(FILE *fp)
#else
int get_data(fp)
FILE *fp;
#endif
{
   int i;

   if (error_found(alloc_arrays(), "allocating memory for arrays")) return(1);

   depth_range.min_depth = MAXSHORT;
   depth_range.max_depth = MINSHORT;
   for (i = 0; i < (anc.num_bottles); i++)
      if (fscanf(fp, " %*d %f %f %f %f %f %f %f %f %f %f",
         &pressure[i], &depth[i], &temp[i], &salinity[i],
         &pot_temp[i], &oxygen[i], &po4[i], &no3[i], &no2[i], &sio2[i]) != 10)
         return(1);
      else
      {
         if (pressure[i] == MISSING) pressure[i] = BADFLOAT;
         if (depth[i] != MISSING)
         {
            if (depth[i] > depth_range.max_depth)
               depth_range.max_depth = round(depth[i]);
            if (depth[i] < depth_range.min_depth)
               depth_range.min_depth = round(depth[i]);
         }
         else depth[i] = BADFLOAT;
         if (temp[i] == MISSING) temp[i] = BADFLOAT;
         if (salinity[i] == MISSING) salinity[i] = BADFLOAT;
         else if (salinity[i] < 0)           /* neg salinity => estimated */
            salinity[i] = fabs(salinity[i]); /* strip sign */
         if (pot_temp[i] == MISSING) pot_temp[i] = BADFLOAT;
         if (oxygen[i] == MISSING) oxygen[i] = BADFLOAT;
         if (po4[i] < 0) po4[i] = BADFLOAT;
         if (no3[i] < 0) no3[i] = BADFLOAT;
         if (no2[i] < 0) no2[i] = BADFLOAT;
         if (sio2[i] < 0) sio2[i] = BADFLOAT;
      }
   return(0);
}

int alloc_arrays()
{
   if ( (pressure = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (depth    = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (temp     = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (salinity = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (pot_temp = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (oxygen   = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (po4      = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (no3      = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (no2      = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   if ( (sio2     = (FLOAT *) calloc(anc.num_bottles, sizeof(FLOAT))) == NULL) return(1);
   return(0);
}
