#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "cf_tags.h"
#include "base_fnx.h"
#include "base_raw2.h"

//--global definitions---------------------------
//--these are extern defines in base_raw2.h for other files
#define RAW2_GLOBAL 1
	
int UxSrf[ ND_MAX ]; // CF_DIVE profile index->surf index array
unsigned long UxTm1[ ND_MAX ], UxTm2[ ND_MAX ]; //CF_DIVE dive start, profile start times
	
int Pdat[ NP_MAX ][  MAX_PDAT ]; // One dive profile data
int Edat[ NP_MAX ][  MAX_EDAT ]; // One dive engineering data
int Eng [ ND_MAX ][  N_ENG    ]; // One eng packet per dive
float WLat[ND_MAX], WLon[ND_MAX]; // waypoint lat & lon arrays
float GPS[4][ ND_MAX][ N_GPS  ]; // all of the GPS info

//---ADP globals
int K_adp; // output index: next open spot
int Hadp [ MAX_ADP_H ]; //most-recently-read ADP info
int Dadp [ NADP_MAX][ MAX_ADP_LINE ]; //integer inputs for one profile





//*****************************************************************************
void  init_global0 ( void ) //*************************************************
{ // initialize the global arrays that span all dives
  
  int j, k, i;
  for (j=0;j<ND_MAX; j++)
  {
    WLat[j] = 0; WLon[j] = 0;
    UxSrf[j] = 0;
    UxTm1[j] = 0;
    UxTm2[j] = 0;
    for (k=0;k<N_ENG;     k++) { Eng[j][k]  = 0; } // zero out the eng. array
    for (i=0;i<4;i++)
    { for (k=0;k<N_GPS;k++) { GPS[i][j][k] = 0; } }
  }
  
  for (k=0;k<MAX_ADP_H; k++) { Hadp[k] = 0; } // ADP header info

  return;
} //***************************************************************************

void  init_pro_global ( void ) //**********************************************
{ // initialize the global arrays for each profile
  
  int j, k;
  for (j=0;j<NP_MAX; j++)
  {
    for (k=0;k<MAX_PDAT;k++) { Pdat[j][k] = 0; } 
    for (k=0;k<MAX_EDAT;k++) { Edat[j][k] = 0; } 
  }
  
  
  //---init the ADP stuff
  K_adp = 0; //next available output index
  for (j=0; j<NADP_MAX; j++) //jjjjjjjjjjjjjjjjjj
  {
    for (k=0; k<MAX_ADP_LINE; k++)
    { Dadp[j][k] = 0;
    }
    
  } //jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
  
  return;
} //***************************************************************************


int   get_dive_mark ( FILE *fp ) //********************************************
{   // read in until dive/profile marker is found
    // returns the profile #
    // returns -1 if EOF
    
    int  n, good=0, p_id, npro=-1;
    char line[NLINE];
    
    //===== read in until dive marker is found ============================
    do
    { // look for marker = 0x0f
      p_id = -1; // init to undefined
      n = fget_line(fp,line,NLINE); // get the next line
      sscanf(line,"%x", &p_id);  // assign packet id
      good = (  n>0 && p_id == CF_DIVE );

      if (good) //-------------------------------------------
      {  // then read the line for content into global variables
         npro = store_flash_CF_DIVE( line );
         good = npro>=0; //read in correct info!
      } //---------------------------------------------------
      
    } while ( !good && n>0 );
    //=====================================================================
    if (!good) return (-1);
    
    
    return( npro );
} //***************************************************************************


int   get_dive ( FILE *fp, int *npts, int *jEng ) //***************************
{   // read data until next dive/profile marker is found
    // returns the NEXT profile #
    // returns -1 if next is EOF
    // returns npts= #points read into the global arrays
    // returns jEng = pointer to where the engineering was stored
    
    int ifile=-1, n, done=0, good=0,  eof, npro=-1, gdive;
    int j=-1, p_id;
    
    char line[NLINE];
    
    init_pro_global(); // make sure ready to read in everything
    // read in data until hit the next dive marker
    do //==================================================================
    { 
       p_id = -1; // init to undefined
       n = fget_line(fp,line,NLINE); // get the next line
       eof = (n<=0); //defines end-of-file
       if ( !eof )
       { // then read in accordingly ---------------------------------
         sscanf(line,"%x", &p_id);  // assign packet id
         switch(p_id) //+++++++++++++++++++++++++++++++++++++++++++
         { // parse according to the packet id
           case CF_PDAT : // profile data
                          j++; // incr the pointer to the output array
                          store_flash_Pdat(j, line); // store the data in global
                          // stores line to Pdat
                          break;
           case CF_EDAT : // eng. data; use same j as used for Pdat
                          store_flash_Edat(j, line); // store the data in global
                          break;
           case CF_ENG  : // engineering packet
                          *jEng = store_flash_eng(line);
                          break;
           case CF_GPS0: 
           case CF_GPS1: 
           case CF_GPS2: 
           case CF_GPS3  : // GPS packet: gdive = surface dive #
                          gdive = store_flash_GPS(line);
                          break;
           case CF_DIVE : // dive marker packet
                          npro = store_flash_CF_DIVE( line );
                          done = 1; //found next packet, end now
                          break;
           case CF_ADP_H  : // ADP Header packet
                          store_flash_adp_h(line);
                          break;
           case CF_ADP    : // ADP Header packet
                          store_flash_adp(line);
                          break;
         } //++++++++++++++++++++++++++++++++++++++++++++++++++++++
       } //-----------------------------------------------------------

    } while (!done && !eof); //============================================
    
    *npts = j; // # of data points found
    //printf("%4d %3d %3d\n",npro, j, K_adp);
    
    if (eof) return(-1);
        
    
    return(npro); // else return the NEXT profile #
} //***************************************************************************



int   store_flash_CF_DIVE (  char s[]  ) //************************************
{  // store the dive marker info
   // return the profile #: <0 = bad

   int ksrf, kcyc, kpro, n ;
   unsigned long ux1, ux2;
   
   n =sscanf(&s[3],"%d %d %d %ld %ld",
             &ksrf, &kcyc, &kpro, &ux1, &ux2 );
  if ( kpro>=0 && kpro < ND_MAX   && n==5 ) //===================
  { // store the data to global array
     UxTm1[kpro] = ux1;
     UxTm2[kpro] = ux2;
     UxSrf[kpro] = ksrf;
  }  //==========================================================
  else 
  { 
    kpro = -1; 
    printf("BAD Dive marker: %s\n",s);
  } // flag as bad
     
  return(kpro);
} //***************************************************************************



void  store_flash_Pdat ( int j, char s[]) //***********************************
{  // store the profile data info from the flash packet
   // j = index to store to 

   int k, n, n1;
   int dat[MAX_PDAT];
   int Npro = MAX_PDAT; // expect up to10 variables 
   // = Surf#, Cycle#, Pro#, tm, P, T, S, Opt,  SBE_on, [DOx]
   n1 = Npro -1;
   
  n = read_ints(&s[3], Npro, dat); //read up to 9 ints, skipping over 2-char tag 

  if (n==Npro || n==n1 ) //======================================
  { // store the data to global arrays, whether it has DOx or not
     for (k=0;k<n; k++) Pdat[j][k] = dat[k];
  }  //==========================================================
     
   return;
} //***************************************************************************




void  store_flash_Edat ( int j, char s[]) //***********************************
{  // store the profile data info from the flash packet
   // j = index to store to 

   int k, n ;
   int  d[MAX_EDAT];
   int Ne = MAX_EDAT; // expect up to Ne variables 
   // = Surf#, Cycle#, Pro#, Head, Pitch, Roll, AD_Pi, AD_Ro, 
   // BAT*100, AMPS*100, OIL, BAT07*100, ALT, ERR
   
  n = sscanf(&s[3],"%d %d %d %d %d %d"
                  "%d %d %d %d %d %d %x",
            &d[0],&d[1], &d[2], &d[3], &d[4], &d[5],
      &d[6],&d[7],&d[8], &d[9],&d[10],&d[11],&d[12]  );

  if ( n == Ne   ) //============================================
  { // store the data to global arrays
     for (k=0;k<n; k++) Edat[j][k] = d[k];
  }  //==========================================================
     
   return;
} //***************************************************************************


int   store_flash_eng ( char s[]) //*******************************************
{  // store the eng info from the flash packet
   // this data is once per profile, and is a mix of float and int values;
   // returns the profile # that the data was stored at.

   int k, id, n, jp;
   int d[N_ENG];
   float wlat, wlon;
   //--line description
   // id = CF_ENG
   // d0 = surface number(increments for each surface comms)
   // d1 = cycle number (normally 0: is higher if multiple cycles/surfacing)
   // d2 = profile number( increments for each profile)
   // d3 = zmax = max depth for this profile
   // d4 = ADP altimeter bottom return signal strength[dB]
   // d5 = alt = distance [m] to the bottom (99=none detected).
   // d6 = b14 = average pump battery Volts for deep pump (V*100)
   // d7 = amp = avg pump amps for deep pump (amps*100)
   // d8 = p0 = surface pressure counts
   // d9 = pi = target pitch
   // d10= he = target heading to steer
   // d11= drx = DR x distance traveled [m]
   // d12= dry = DR y distance traveled [m]
   // wlat= Wlat= Waypoint latitude
   // wlon= Wlon= Waypoint longitude
   // d13= Nbad= #times high pump current was detected
   // d14= Navg= #8s scans avg'd for each output satellite datum
   // d15= Tpmp1= time[1 cnt=10s] to pump until neutral
   // d16= Tpmp2= remaining time[1 cnt=10s] pumped: Tpmp1=Tpmp2 = total pmp time
   // d17= Vac = vacuum sensor [in-Hg *10]
   // d18= tI time[ 1 cnt=10s] that max pump current occurred.
   // d19 =mI = max pump current [1 cnt= 0.02 amps]
   // d20 =eR = accum. roll error at the bottom of descent [1 cnt=0.1 deg]
   // d21 =ts = time sent sending SBD [s]
   // d22 =nt = #tries to send messages
   // d23 =ns = #actually sent
   // d24 = w = wing ID: 1=port, 0=stbd
   // d25 = si= status of SBD messages sent
   // d26 = ss= status of parsing the shore cmd
   // d27 = st2=end-dive surface time [1 cnt=10s].
   // d28 = st1=start-dive time to leave the surface [1 cnt=10s]
   // d29 = za = depth at time of the altimeter reading
   // d30 = vt = time that the air vent ran
   // d31 = vs = vent status: bit0=1 if air@start, bit1=1 if air@end 
   // d32 = ex = exception status (hex; ea bit=error exception if set)
   
   
   // read in all of the variables
   n = sscanf(s,"%x %d %d %d %d %d %d %d %d %d %d %d %d %d"  
                "%f %f %d %d %d %d %d %d %d %d %d %d %d"  
                "%d %d %d %d %d %d %d %d %x",             
                 &id,  &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], 
                 &d[7], &d[8],&d[9],&d[10],&d[11],&d[12],
                 &wlat,&wlon,&d[13],&d[14],&d[15],&d[16],&d[17],&d[18],
                 &d[19],&d[20],&d[21],&d[22],&d[23],&d[24],&d[25],
                 &d[26],&d[27],&d[28],&d[29],&d[30],&d[31], &d[32]  );
   
   // store to the big eng array
   jp = -1; // set to illegal value
  if ( n == 36   ) //============================================
  { // store the data to global arrays
  	jp = d[2]; //=profile #
 	if (jp>=0 && jp<ND_MAX)
  	{ // then is legal
     	for (k=0;k<n; k++) Eng[jp][k] = d[k];
    	WLat[jp] = wlat;
     	WLon[jp] = wlon;
    } 
    else
    { printf("ILLEGAL Profile # in ENG packet = %d\n",jp); }
  }  //==========================================================
   
     
   return(jp);
} //***************************************************************************



int   store_flash_GPS ( char s[]) //*******************************************
{  // store the GPS info from the flash packet
   // this data is once per profile, and is a mix of float and int values;
   // returns the surface dive # that the data was stored at.

   int k, id, n, jd;
   float d[N_GPS];

   //--line description
   // id = CF_GPS 0=start-mission, 1=start-dive, 2=end-dive, 3=abort
   			// used to store to first index of 2-D float array
   // d0 = surface number(increments for each surface comms)
   // d1 = valid-flag
   // d2 = year
   // d3 = year-day
   // d4 = Latitude
   // d5 = Longitude
   // d6 = HDOP
   // d7 = Acquire-Time
   // d8 = Number of satellites
   // d9 = Smin
   // d10= Savg
   // d11= Smax
   // d12= utc_hr
   // d13= utc_mn
   // d14= utc_sec
   
   
   // read in all of the variables
   n = sscanf(s,"%x %f %f %f %f %f %f %f %f %f %f %f %f %f:%f:%f",  
                 &id,  &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], 
                 &d[7], &d[8],&d[9],&d[10],&d[11],&d[12],
                 &d[13],&d[14] );
   
   // store to the big GPS array
   jd = -1; // set to illegal value
   if ( id<0 || id>3 )
   { //-- illegal GPS id #  !
     printf("ILLEGAL GPS ID #=%d\n",id);
     return(-1);
   }
  if ( n == (N_GPS+1)   ) //============================================
  { // store the data to global arrays
  	jd = (int) d[0]; //=surface #
 	if (jd>=0 && jd<ND_MAX)
  	{ // then is legal
     	//printf("GPS %1d %4d ",id, jd );
     	for (k=0;k<N_GPS; k++) 
     	 { GPS[id][jd][k] = d[k];
     	   //printf(" %8.3f ",d[k] );
     	 }
     	 //printf("\n");
    } 
    else
    { printf("ILLEGAL Dive # in GPS packet = %d\n",jd); }
  }  //==========================================================
  else { printf("WRONG # of arguments in GPS line = %d\n", n); }
   
     
   return(jd);
} //***************************************************************************


void  store_flash_adp_h (  char s[]  ) //**************************************
{  // store the ADP header info from the flash packet

   int k, n ;
   int d[MAX_ADP_H];
   float dp1;
   
  n = read_ints(&s[3], MAX_ADP_H, d); //read up to MAX_ADP_H ints, skipping over 2-char tag 

  if (n==MAX_ADP_H ) //======================================
  { // store the data to global array
  	//--compute where the center of the 1st bin should be
    dp1 = d[ADP_BD]*0.1 + (d[ADP_CSIZE] + d[ADP_PULSE])*0.5;  // center of the first bin
    d[ADP_BIN0] = (int) ( dp1*10 + 0.5);

     for (k=0;k<MAX_ADP_H; k++) 
     {
       Hadp[k] = d[k];
       //printf("%8d  ",d[k]);
     }
     //printf("\n");
     
  }  //==========================================================
     
     
   return;
} //***************************************************************************

void  store_flash_adp   (  char s[]  ) //**************************************
{  // store the ADP header info from the flash packet

   int k, n ;
   int d[MAX_ADP_LINE];
   
  n = read_ints(&s[3], MAX_ADP_LINE, d); 
  //array= surf#, cyc#, pro#, pr, he, pi, roll,
  // (beam 1, 2, 3) noise 
  // (beam1[ Ncell of amp], beam2[Ncell of amp], beam3[Ncell of amp]
  // ditto for velocity

  // for Ncell=5, beam=3, have 7+3 + 15+15 = 40 points per line
  // if Ncell=2, 22 points per line
  if ( n>21 && K_adp< NADP_MAX  ) // could be real
  { //===========================================================
     for (k=0;k<n; k++) 
     {
       Dadp[K_adp][k] = d[k];
     }
     K_adp++;
  }  //==========================================================
     
     
   return;
} //***************************************************************************




//**** end ********************************************************************
//*****************************************************************************

 