#ifndef SMARTSAMPLER_Interfaces_HH
#define SMARTSAMPLER_Interfaces_HH

#define PROFILE_FROM_DEPTH true

#include "ClusterIF.h"
#include "GulperIF.h"
#include "CtdIF.h"
#include "IsusIF.h"
#include "HydroscatIF.h"
#include "DepthSensorIF.h"
//#include "NavigationIF.h"
#include "TimeP.h"
#include "ShortData.h"
#include "DoubleData.h"
#include "FloatData.h"
#include <vector>
// I have my own fake versions for testing
#ifdef SELF_TEST
#include "FakeCTD.hh"
#include "FakeHS2.hh"
#include "FakeIsus.hh"
#include "FakeDepthSensor.hh"
#endif

#ifndef PROFILE_FROM_DEPTH
// There is no direct method other than the fake one for now.  If one comes up,
// This should go into SELF_TEST.
#include "FakeProfile.hh"
#endif

/****************************************************************************
 *
 * SmartSamplerInterfaces (SSI) class provides a unified socket for
 * attaching to other servers (and makes sure we don't open multiple
 * sockets to the same server).  This includes the data interfaces as
 * well as the gulper and nav.
 *
 * WARNING: SSI is meant to be used directly only by the
 * SmartSamplerData (SSD) class and by SmartSampler itself.
 * DecisionTools should access data through SSD.
 *
 ****************************************************************************/

// these structs communicate two ways between SSI and SSD.
typedef struct{
  bool isnew;            // SSI->SSD: tells if time changed between previous version and current
  bool track;            // SSD->SSI: tell SSI we are tracking this guy
  double val;            // SSI->SSD: last value read from device
}ssi_double_t;
typedef struct{
  bool isnew;
  bool track;
  float val;
}ssi_float_t;
typedef struct{
  bool isnew;
  char *classifier;
  short best;
  double dist;
}ssi_cluster_t;

class SmartSamplerInterfaces{
public:

  SmartSamplerInterfaces();
  ~SmartSamplerInterfaces();

  // Pick up data for SmartSamplerData.  This should all be done more
  // generically in the future!  All times are in double precision
  // seconds.  I think this precision should be enough, and it
  // certainly simplifies things.  Only modify given values if the track
  // member is true, and all status indicators from device are positive.
  // NOTE -- this time is relative only and has nothing to do with simulation time.
  void updateCTD(ssi_float_t *tempOut,ssi_float_t *condOut,ssi_float_t *salOut,ssi_float_t *oxyOut);
  void updateHS2(ssi_double_t *bbshortOut,ssi_double_t *bblongOut,ssi_double_t *fluorOut);
  void updateIsus(ssi_double_t *nitrateOut);
  void updateCluster(ssi_cluster_t *clOut);
  void updateProfileCount(long *cnt);
  void updateDepth(ssi_double_t *depthOut);

  // For SmartSampler
  bool gulperState(GulperIF::gs10 state);
  bool fireGulper(int num);
  
  //  NavigationIF *attachNav();
  bool attachCluster();
  bool attachCTD();
  bool attachHS2();
  bool attachIsus();
  bool attachGulper();
  bool attachProfileCounter();
  bool attachDepthSensor();

private:
#ifdef SELF_TEST
  FakeCTD         *ctd_ifp;
  FakeHS2         *hs2_ifp;
  FakeIsus        *isus_ifp;
  FakeDepthSensor *depth_ifp;
#else
  CtdIF           *ctd_ifp;
  HydroscatIF     *hs2_ifp;
  IsusIF          *isus_ifp;
  DepthSensorIF   *depth_ifp;
#endif // NOT SELF_TEST
#ifndef PROFILE_FROM_DEPTH
  // This should be turned into the real thing at some point.
  FakeProfile      *prof_ifp;
#endif
  GulperIF        *gulper_ifp;
  ClusterIF       *cluster_ifp;

  // We need to store time values for comparison.
  typedef struct{
    long secs;
    short hsecs;
  }hs2time_t;
  hs2time_t ptime_hs2;
  TimeIF::TimeSpec ptime_temp,ptime_cond,ptime_depth;

  // I'm surprised < is not overloaded for TimeSpec, but I didn't see it anywhere.
  bool timeLessThan(TimeIF::TimeSpec t1,TimeIF::TimeSpec t2){
    return((t1.seconds < t2.seconds) || 
	   ((t1.seconds == t2.seconds) && (t1.nanoSeconds < t2.nanoSeconds)));
  };
  bool timeLessThan(hs2time_t t1, hs2time_t t2){
    return((t1.secs < t2.secs) || ((t1.secs == t2.secs) && (t1.hsecs < t2.hsecs)));
  };
}; // SmartSamplerInterfaces

#endif // SMARTSAMPLER_Interfaces_HH 
