/****************************************************************************/
/* 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 "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

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;
  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, _lastGulpTime, _timeStartCheckingGulpers;
  double _fl676_AvgProfile, _bb470_AvgProfile, _bb676_AvgProfile;
  double _fl676_avg_profile[MAXSTOREDPROFILES], _bb470_avg_profile[MAXSTOREDPROFILES], _bb676_avg_profile[MAXSTOREDPROFILES], _flMaxOnProfile, _fl_maxOnProfile[MAXSTOREDPROFILES], _flMaxOnProfile_avg, _flMaxOnPrecedingProfile;
  double _fl676_bkgnd, _bb470_bkgnd, _bb676_bkgnd, _alpha_fl, _alpha_bb, _var_min, _var_max, _var_bkgnd, _alpha_var, _beta_fl, _beta_bb;
  double _fl676_lp[3], _bb470_lp[3], _bb676_lp, *_ptr_var_lp, _fl676_maxInWindow, _bb470_maxInWindow, _bb676_maxInWindow, _fl676_sumInWindow, _bb470_sumInWindow, _bb676_sumInWindow;
  double _fl676_inwindow[MAXFILTERLEN], _bb470_inwindow[MAXFILTERLEN], _bb676_inwindow[MAXFILTERLEN], *_ptr_var_inwindow;
  double _peak[MAXSTOREDPEAKS], _timeCntr_peak[MAXSTOREDPEAKS], _peak_baseline, _peak_saved, _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_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;
  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 _minfl676[NGULPERS];
  double _maxfl676[NGULPERS];
  double _minbb470[NGULPERS];
  double _maxbb470[NGULPERS];
  double _minbb676[NGULPERS];
  double _maxbb676[NGULPERS];
  double _minTempDiffVert[NGULPERS];
  double _maxTempDiffVert[NGULPERS];
  char  *_config;
  long   _gulperToFire;
  Boolean _gulpArray[NGULPERS][MAXSAMPLES];

  Boolean _test, _depthCheck, _depthCheckMaxWait, _tempCheck, _salCheck;
  Boolean _fl676Check, _bb470Check, _bb676Check, _peakCheck, _upwellingCheck, _valleyCheck, _frontCheck, _tempDiffVertCheck, _crossingDepFlMaxOnPrecedingProfileCheck;
  char  _gnum;
  short _cntr, _state_var, _state_dep[2], _state_dep_1stpk, _flag_1stpk, _flag_ctrl, _flag_peakOrCtrlTriggered, _attitude_flop, _attitude_flop_flop, _pk_ctrl, _flag_startCheckingGulpers;
  long _option_PTL_INL, _option_into_upwelling, _option_BaselineWindow_RunningOrSliding, _option_ClosenessOfTwoCrossings, _option_PeaksAtSurface, _option_Front_TempOrFl, _ratio_pktrigs_ctrltrigs, _cntr_fl_bb, _cntr_peak, _cntr_trig, _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;

  FILE *_ptr_input_file;

  GulperIF::gs10 _gulperDriverState;
};

#endif
