/****************************************************************************/
/* Copyright (c) 2006 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : AdaptiveSampler.h                                             */
/* Author   : Rob McEwen                                                    */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 12/01/2006                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#ifndef _AdaptiveSampler_H
#define _AdaptiveSampler_H
#include "PeriodicTask.h"
#include "AdaptiveSamplerIF.h"
#include "GulperDefs.h"
#include "GulperIF.h"
#include "NavigationIF.h"
#include "CtdIF.h"
#include "HydroscatIF.h"
#include "DepthSensorIF.h"
//#include "BiolumeIF.h"
#include "AdaptiveSamplerLog.h"
#include "AdaptiveSamplerOutput.h"
#include "Attributes.h"

#define SHALLOWLIMIT_DEPTH 0.0
#define LOWERLIMIT_FL_BB 0.0
#define UPPERLIMIT_FL_BB 1.0
#define MAXSAMPLES 128
#define MAXFILTERLEN 100
#define MAXSTOREDPEAKS 200
#define MAXSTOREDPROFILES 20
#define MAXSTOREDDEPTHS 10
#define MAXNUMPEAKSIGNALS 2

class AdaptiveSampler : public PeriodicTask {

  friend class AdaptiveSamplerLog;

public:

  AdaptiveSampler( Boolean test = False, 
		   char *configFile = "adaptiveSampler.cfg");
  ~AdaptiveSampler();

  ////////////////////////////////////////////////////////////////////
  // Initialize device. Returned DeviceIF::Status
  // will be propagated to subscribers in other tasks.
  void initialize();
  void readData();

  ////////////////////////////////////////////////////////////////////
  // Read a fixed-length record - use the default:

  ////////////////////////////////////////////////////////////////////
  // Process device data record. Returned DeviceIF::Status
  // will be propagated to subscribers in other tasks.
  // [input] record: Record from device
  // [input] nRecordBytes: Bytes in record


protected:

  GulperIF      *_gulper;
  NavigationIF  *_nav;
  CtdIF         *_ctd, *_ctd2;
  HydroscatIF   *_hydroscat;
  DepthSensorIF *_parosci;
//BiolumeIF     *_biolume;

  AdaptiveSamplerLog *_log;
  AdaptiveSamplerOutput *_output;

  Attributes _attributes;
  const long NotSpecified;
      
  void createCfgAttributes();
  void loadConfigFile(const char* file);
  void printCfgAttributes();
  void peakDetection();

private:

  NavigationIF::Position _position;
  NavigationIF::Attitude _attitude;
  float _salinity, _temperature;
  double _depth;

  HydroscatIF::Data _hs2data;
  TimeIF::TimeSpec _condTime, _condTimeLast, _tempTime, _tempTimeLast;
  TimeIF::TimeSpec _depthTime, _depthTimeLast;
  double _hs2LastSeconds, _hs2LastMicroSeconds, _fl676, _bb470, _bb676, _rhod, _lastGulpTime, _timeGulperArmed[NGULPERS], _lastGulpDepth;
  double _fl676_AvgProfile, _bb470_AvgProfile, _bb676_AvgProfile, _rhod_AvgProfile;
  double _fl676_avg_profile[MAXSTOREDPROFILES], _bb470_avg_profile[MAXSTOREDPROFILES], _bb676_avg_profile[MAXSTOREDPROFILES], _rhod_avg_profile[MAXSTOREDPROFILES], _flMaxOnProfile, _fl_maxOnProfile[MAXSTOREDPROFILES], _flMaxOnProfile_avg, _flMaxOnPrecedingProfile, _rhodMaxOnProfile, _rhodMaxOnPrecedingProfile;
  double _fl676_bkgnd, _bb470_bkgnd, _bb676_bkgnd, _rhod_bkgnd, _alpha_fl, _alpha_bb, _alpha_rhod, _var_min[MAXNUMPEAKSIGNALS], _var_max[MAXNUMPEAKSIGNALS], _var_bkgnd, _alpha_var, _beta_fl, _beta_bb, _beta_rhod;
  double _fl676_lp[3], _bb470_lp[3], _bb676_lp, _rhod_lp[3], *_ptr_var_lp, _fl676_maxInWindow, _bb470_maxInWindow, _bb676_maxInWindow, _fl676_sumInWindow, _bb470_sumInWindow, _bb676_sumInWindow, _rhod_maxInWindow, _rhod_sumInWindow;
  double _fl676_inwindow[MAXFILTERLEN], _bb470_inwindow[MAXFILTERLEN], _bb676_inwindow[MAXFILTERLEN], _rhod_inwindow[MAXFILTERLEN], *_ptr_var_inwindow;
  double _peak[MAXNUMPEAKSIGNALS][MAXSTOREDPEAKS], _timeCntr_peak[MAXNUMPEAKSIGNALS][MAXSTOREDPEAKS], _peak_baseline[MAXNUMPEAKSIGNALS], _peak_saved[MAXNUMPEAKSIGNALS], _timewindow_peakbaseline;
  double _thresh_TempDiffInUpwelling, _tempDep[MAXSTOREDDEPTHS], _tempDepAvg, _temp_diff[MAXSTOREDPROFILES], _tempDiffSumInWindow, _temp_diff_lp[MAXSTOREDPROFILES], _step_TempDiffInTempFront, _thresh_TempDiffInTempFront, _step_FlInFlFront;
  double _dep[MAXSTOREDDEPTHS], _dep_min, _dep_max, _dep_shallow, _dep_deep, _delta_fl_bb_rise, _delta_fl_bb_drop, _delta_rhod_rise, _delta_rhod_drop, _delta_var_rise, _delta_var_drop, _delta_dep, _timeFromDataFile, _dep_shallow_upwelling, _dep_deep_upwelling, _dep_midshallow_upwelling, _dep_middeep_upwelling, _dep_shallow_fl;
  double _dep_minFrontTriggering, _dep_maxFrontTriggering, _dep_flMaxOnProfile, _dep_flMaxOnPrecedingProfile, _dep_rhodMaxOnProfile, _dep_rhodMaxOnPrecedingProfile;
  double _timeLockOutPeak[NGULPERS], _timeLockOutUpwelling[NGULPERS], _timeLockOutFront[NGULPERS], _timeLockOutAtStart[NGULPERS], _timeMaxWait[NGULPERS];

  long   _peakDetection[NGULPERS], _upwellingDetection[NGULPERS], _frontDetection[NGULPERS];
  long   _GulperNumberFiredBefore[NGULPERS], _GulperNumberRefMaxWait[NGULPERS];
  long   _repeat[NGULPERS];
  long   _nSamples[NGULPERS];
  long   _nGood[NGULPERS];
  double _minDepth[NGULPERS];
  double _maxDepth[NGULPERS];
  double _minDepthMaxWait[NGULPERS];
  double _maxDepthMaxWait[NGULPERS];
  double _minSal[NGULPERS];
  double _maxSal[NGULPERS];
  double _minTemp[NGULPERS];
  double _maxTemp[NGULPERS];
  double _minDepChange[NGULPERS];
  double _minfl676[NGULPERS];
  double _maxfl676[NGULPERS];
  double _minbb470[NGULPERS];
  double _maxbb470[NGULPERS];
  double _minbb676[NGULPERS];
  double _maxbb676[NGULPERS];
  double _minrhod[NGULPERS];
  double _maxrhod[NGULPERS];
  double _minTempDiffVert[NGULPERS];
  double _maxTempDiffVert[NGULPERS];
  char  *_config;
  Boolean _gulpArray[NGULPERS][MAXSAMPLES];

  Boolean _test, _depthCheck, _depthCheckMaxWait, _tempCheck, _salCheck;
  Boolean _fl676Check, _bb470Check, _bb676Check, _rhodCheck, _peakCheck[MAXNUMPEAKSIGNALS], _upwellingCheck, _valleyCheck, _frontCheck, _tempDiffVertCheck, _crossingDepFlMaxOnPrecedingProfileCheck, _crossingDepRhodMaxOnPrecedingProfileCheck;
  char  _gnum;
  short _cntr, _state_var[MAXNUMPEAKSIGNALS], _state_dep[2], _state_dep_1stpk[MAXNUMPEAKSIGNALS], _flag_1stpk[MAXNUMPEAKSIGNALS], _flag_ctrl[MAXNUMPEAKSIGNALS], _flag_peakOrCtrlTriggered, _attitude_flop[MAXNUMPEAKSIGNALS], _attitude_flop_flop[MAXNUMPEAKSIGNALS], _pk_ctrl[MAXNUMPEAKSIGNALS], _flag_gulperArmed[NGULPERS], _flag_AllFired, _num_PeakSignals, _indSignalCapture, _cntr_gulp;
  long _option_FireAll, _option_PTL_INL, _option_RHOD, _gulps_ChlOrRhod, _option_into_upwelling, _option_BaselineWindow_RunningOrSliding, _option_ClosenessOfTwoCrossings, _option_PeaksAtSurface, _option_Front_TempOrFl, _ratio_pktrigs_ctrltrigs, _cntr_fl_bb, _cntr_rhod, _cntr_peak[MAXNUMPEAKSIGNALS], _cntr_trig[MAXNUMPEAKSIGNALS], _len_window_full, _timeCntr, _num_profiles_BaselineWindow, _cntr_PtsOnProfile, _cntr_profiles, _cntr_ProfilesInUpwelling, _thresh_NumProfilesInUpwelling, _cntr_ProfilesTempDiff, _num_ProfilesAvgTempDiff, _num_ProfilesGapTempDiff, _cntr_ProfilesInTempFront, _thresh_NumProfilesInTempFront, _num_ProfilesAvgFl, _num_ProfilesGapFl, _num_ProfilesFl, _thresh_NumProfilesInFlFront, _cntr_ProfilesFl, _cntr_ProfilesInFlFront;
  short _flag_temp_shallow, _flag_temp_midshallow, _flag_temp_middeep, _flag_temp_deep, _flag_tempdiff_enabled, _flag_temp_front;
  short _flag_fl_shallow, _flag_fl_front, _flag_crossingDepFlMaxOnPrecedingProfile, _flag_crossingDepRhodMaxOnPrecedingProfile;

  FILE *_ptr_input_file;

  GulperIF::gs _gulperDriverState;
};

#endif
