/******************************************************************************
*
    PROGRAM:  BOTMPAS3.C
    USAGE:    BOTMPAS3 <dbname>

       This program retrieves the max_amp_bin and
       last_good_bin data in the ANCILLARY_2 structure for
       three consecutive profiles at a time, and assigns the
       smallest bin no. among these as the last_good_bin for
       the middle profile.  The updated ancillary structure
       is then stored back in the database.

       It turns on bit 9 of the data processing mask for each block to
       indicate that the database has been edited in this manner.

       It also updates the last_good_bin field of the ACCESS_VARIABLES
       structure to the same value as ANCILLARY_2's last_good_bin, if
       the latter has a smaller value.

       J. Ranada - 03/21/88 - University of Hawaii JIMAR
       Updated   - 05/18/88 - to use new ADCP format in ADCP.H
       Updated   - 05/24/89 - to check if mask has already been set, then
                              skip the block (to permit processing of
                              partial databases during acquisition)
                              NOTE *** running this program repeatedly
                              as the database is appended to is NOT
                              recommended because it can result in slightly
                              more stringent assessment of the first
                              profile in the added section due to loss of
                              information from the preceding run.
                                                                              *
******************************************************************************/

#include "geninc.h"
#include "data_id.h"                   /* CODAS variable names and IDs   */
#include "adcp.h"                      /* ADCP data structures           */
#include "ioserv.h"                    /* error_found()                  */
#include "use_db.h"                    /* db*_cnf(),  set_dpmask()       */
#include "dbedit.h"                    /* update_acc_var()               */
#include "dpmask.h"                    /* BOTTOM_SOUGHT                  */

#if PROTOTYPE_ALLOWED
int update_db(ANCILLARY_2_TYPE *anc, SHORT save);
int alloc_structs(void);
#else
int update_db();
int alloc_structs();
#endif

#define NMAX 128                        /* max. no. bins */
#define dbname argv[1]

ANCILLARY_2_TYPE *anc1,*anc2,*anc3;     /* consider 3 profiles at a time */

#if PROTOTYPE_ALLOWED
int main(int argc, char *argv[])
#else
int main(argc, argv)
int argc;
char *argv[];
#endif
{
   SHORT            save_lgb;
   ANCILLARY_2_TYPE *temp;
   int              ierr, nsteps, iblkprf[2], set;
   unsigned int     n;

   if (argc < 2)
   {
      printf("\n ERROR: Invalid no. of arguments");
      printf("\n USAGE: BOTMPAS3 <dbname>\n\n");
      exit(-1);
   }

   if (error_found(alloc_structs(),
      "allocating memory for ancillary structures")) exit(-1);
   if (dbopen_cnf(1, dbname, READ_WRITE, DIR_IN_MEMORY)) exit(-1);

   /*-----------------------------------------------------------------
      LOCATE FIRST BLOCK NOT YET PROCESSED AS INDICATED BY D.P. MASK
     -----------------------------------------------------------------*/
   iblkprf[0] = -1; iblkprf[1] = 0;
   do
   {
      iblkprf[0]++;
      if (dbsrch_cnf(BLOCK_PROFILE_SEARCH, (char *) iblkprf)) goto close;
      if (error_found( ((set = check_block_dpmask(BOTTOM_SOUGHT)) == -1),
         "checking data processing mask")) goto close;
   } while (set);

   if (iblkprf[0] != 0)                 /* need to update last profile of */
      if (dbmove_cnf(-1)) goto close;   /* preceding block from last run  */

   /*-------------------------------------------------------------
       FIRST PROFILE IS UPDATED USING DATA FOR TWO PROFILES ONLY
     -------------------------------------------------------------*/
   n = sizeof(ANCILLARY_2_TYPE);
   if (dbget_cnf(ANCILLARY_2, (char *) anc1, &n, "getting ancillary data"))
      goto close;
   if (dbmove_cnf(1)) goto close;
   n = sizeof(ANCILLARY_2_TYPE);
   if (dbget_cnf(ANCILLARY_2, (char *) anc2, &n, "getting ancillary data"))
      goto close;

   save_lgb = anc1->last_good_bin;
   anc1->last_good_bin = min_val(anc1->max_amp_bin, anc2->max_amp_bin);
   if (dbmove_cnf(-1)) goto close;
   if (error_found(update_db(anc1, save_lgb), "updating database")) goto close;

   /*---------------------------------------------------------
       MAIN PROCESSING LOOP FOR EACH GROUP OF THREE PROFILES
     ---------------------------------------------------------*/
   do
   {
      nsteps = 2;
      DBMOVE(&nsteps, &ierr);
      if (ierr)
      {
         if (ierr != SEARCH_BEYOND_END)
         {
            printf("\n ERROR: %d in DBMOVE", ierr);
            goto close;
         }
      }
      else
      {
         n = sizeof(ANCILLARY_2_TYPE);
         if (dbget_cnf(ANCILLARY_2, (char *) anc3, &n, "getting ancillary data"))
            goto close;

         save_lgb = anc2->last_good_bin;
         anc2->last_good_bin = min_val(
                                min_val(anc2->max_amp_bin, anc1->max_amp_bin),
				min_val(anc2->max_amp_bin, anc3->max_amp_bin));

         if (dbmove_cnf(-1)) goto close;
         if (error_found(update_db(anc2, save_lgb), "updating database"))
            goto close;
      }

      /*--------------------------------------------------------
          ROTATE ARRAY POINTERS TO LOOK AT NEXT GROUP OF THREE
        --------------------------------------------------------*/
      temp = anc1;
      anc1 = anc2;
      anc2 = anc3;
      anc3 = temp;

   } while (ierr != SEARCH_BEYOND_END);

   /*------------------------------------------------------------
       LAST PROFILE IS UPDATED USING DATA FOR LAST TWO PROFILES
     ------------------------------------------------------------*/
   save_lgb = anc2->last_good_bin;
   anc2->last_good_bin = min_val(anc1->max_amp_bin,anc2->max_amp_bin);

   error_found(update_db(anc2, save_lgb), "updating database");

close:
   dbclose_cnf();
   return(0);
}

#if PROTOTYPE_ALLOWED
int update_db(ANCILLARY_2_TYPE *anc, SHORT save)
#else
int update_db(anc, save)
ANCILLARY_2_TYPE *anc;
SHORT save;
#endif
{
   static int prevblk = -99;
   int iblkprf[2];
   unsigned int n;

   if (anc->last_good_bin != save)
   {
      n = sizeof(ANCILLARY_2_TYPE);
      if (dbput_cnf(ANCILLARY_2, (char *) anc, &n, "storing ancillary data"))
         return(1);
      if (error_found(update_acc_var(anc->last_good_bin),
         "updating access variables")) return(1);
   }
   n = 2 * sizeof(int);
   if (dbget_cnf(BLOCK_PROFILE_INDEX, (char *) iblkprf, &n,
      "getting block-profile index")) return(1);
   if (iblkprf[0] != prevblk)
   {
       if (error_found(set_block_dpmask(BOTTOM_SOUGHT),
          "setting data processing mask")) return(1);
       prevblk = iblkprf[0];
   }
   return(0);
}

#if PROTOTYPE_ALLOWED
int alloc_structs(void)
#else
int alloc_structs()
#endif
{
   if (((anc1 = (ANCILLARY_2_TYPE *) malloc(sizeof(ANCILLARY_2_TYPE))) == NULL)
      || ((anc2 = (ANCILLARY_2_TYPE *) malloc(sizeof(ANCILLARY_2_TYPE))) == NULL)
      || ((anc3 = (ANCILLARY_2_TYPE *) malloc(sizeof(ANCILLARY_2_TYPE))) == NULL))
      return(1);
   return(0);
}

