#ifndef SMARTSAMPLER_Data_HH
#define SMARTSAMPLER_Data_HH

#include "SmartSamplerInterfaces.hh"
#include "SSDLogger.hh"
#include <vector>

/****************************************************************************
 *
 * SmartSamplerData (SSD) class keeps track of the data being used by
 * various DecisionTools.  Keep a list of current values along with
 * the time of last valid measurement (where applicable).  Although
 * different devices return data and time in different formats, here
 * we force data into a fixed format (make it typedef so we can change),
 * and use double precision seconds for time.
 *
 * In the future, we should think about:
 *
 * 1) Handling of measurement types, and the fact that I'm using a
 *    fixed list of variables is annoying.  Should do something more
 *    general like cluster/devices.
 * 2) If not that, the typecasting of values to data_t could be
 *    handled better, along with dynamically allocating the measurements.
 * 3) We don't associate time with samples, beyond keeping track of whether
 *    or not they are new in the current callback.  That ok?
 * 4) A nice feature would be smoothed data.
 * 5) Add support for switching or averaging between the two ctds.
 *
 ****************************************************************************/

class SmartSamplerData{
public:
  typedef double data_t;

  // These are the measurements which we can just ennumerate directly.
  // I didn't bother with dynamic allocation of these here, just keep
  // an extra bit which tells us if we want to track or not.
  typedef enum{
    ssd_temp=0,        // temperature from ctd
    ssd_sal,           // salinity from ctd
    ssd_cond,          // conductivity from ctd
    ssd_oxy,           // dissolved oxygen from ctd (ctd1 only!)
    ssd_bbshort,       // backscatter short wavelength from hs2
    ssd_bblong,        // backscatter long wavelength from hs2
    ssd_fluor,         // fluorescence product from hs2
    ssd_nitrate,       // nitrate from isus
    ssd_depth,         // depth from depth sensor (parosci)
    ssd_unknown        // placeholder
  }ssd_measurement_t;

  SmartSamplerData(SmartSamplerInterfaces *ssiIn);
  ~SmartSamplerData();

  bool useMeasurement(ssd_measurement_t id); // setup to use given measurement
  bool useCluster(char *classifier); // setup to use cluster
  bool useProfileCounter(); // setup to use profile counter from LayeredControl

  void finishInit(); // a little annoying, but call this when all use* are done.

  // The next guys return true if new this callback.
  bool getMeasurement(ssd_measurement_t id, data_t *val);
  bool getCluster(char *classifier, unsigned short *best, double *dist);
  bool getProfileCount(long *num);

  void update();

  ssd_measurement_t stringToMType(char *stringIn);
  // The output buffer should hold at least 13 characters!
  void mTypeToString(ssd_measurement_t id, char *stringOut);

private:
  friend class SSDLogger;
  SSDLogger ssdlogger;
  bool initdone;

  // Here are the basic data products
  ssi_float_t temperature;
  ssi_float_t conductivity;
  ssi_float_t salinity;
  ssi_float_t oxygen;
  ssi_double_t bbshort;
  ssi_double_t bblong;
  ssi_double_t fluor;
  ssi_double_t nitrate;
  ssi_double_t depth;

  // For cluster, we need a little extra work
  typedef std::vector<ssi_cluster_t>::iterator ssici_t;
  std::vector<ssi_cluster_t> clusters;
  ssici_t findCluster(char *classifier);

  long profilecount;
  bool profilecountnew;

  SmartSamplerInterfaces *ssi;
  bool anyNew();
  void initMStructs(); // Simple initialization for fixed measurement structures.
#ifdef PROFILE_FROM_DEPTH
  // This is t-5:.5:t...
  double depthbuf[11];
  int nextdepthidx;
  bool depthbuffull,descending;
#endif
};

#endif // SMARTSAMPLER_Data_HH 
