#ifndef NMM_MICROSCOPE_H
#define NMM_MICROSCOPE_H

// If you want to look for anything that Tiger changed, just look for 'Tiger'
// inside the file

/*      Tiger   move it to nmm_MicroscopeRemote.h
#ifndef AFM_STATE_H
#include "AFMState.h"
#endif
*/

#ifndef VRPN_CONNECTION_H               // Tiger added it. It was in AFMState.h
#include   // for vrpn_MESSAGEHANDLER
#endif

/*
#ifndef NMM_MICROSCOPE_C_H      // Added by Tiger. We used date type defined
#include "nmm_Microscope_c.h"   // in this header file for some encode and
#endif                          // decode functions, such as encode_ScanDataset
                                // and encode_PointDateset
*/

class vrpn_Connection;

/*      Tiger   moved them to nmm_MicroscopeRemote.h
class nmb_Dataset;  // from nmb_Dataset.h
class nmb_Decoration;  // from nmb_Decoration.h
*/

// nmm_Microscope
//
// Tom Hudson, May 1998

// Base class for microscope controllers.
// Speaks VRPN as the network protocol.
// Declares and initializes network ID for objects of this class
// and for each message type.
// Defines encode() and decode() functions for each message type.


class nmm_Microscope {

  public:

    nmm_Microscope (/*  Tiger   moved it to nmm_MicroscopeRemote
                        const AFMInitializationState &, */
                    const char * name,
                    vrpn_Connection * = NULL);
      // Constructor.
      //   If the Microscope is a server, the Connection should be set up
      // to listen on a port;  if the Microscope is a remote, the
      // connection should have connected to the appropriate server.

    virtual ~nmm_Microscope (void);
      // Destructor. HP compiler doesn't like this declared with "= 0;"

    virtual long mainloop (void);

    enum Direction { Forward, Backward };

/*      Tiger   moved it to nmm_MicroscopeRemote.h
    AFMState state;
*/

    // MANIPULATORS

/* Tiger        moved them to nmm_MicroscopeRemote
    long InitializeDataset (nmb_Dataset *);
    long InitializeDecoration (nmb_Decoration *);
    long InitializeTcl (const char * tcl_script_dir);
      // TODO:  move all of these to AFMInitializationState?
      //   AT LEAST think about passing them in to the constructor.

    nmb_Dataset * Data (void)
      { return d_dataset; }
    nmb_Decoration * Decor (void)
      { return d_decoration; }
*/

  protected:

    vrpn_Connection * d_connection;

/*  Tiger       moved them to nmm_MicroscopeRemote.h
    nmb_Dataset * d_dataset;
    nmb_Decoration * d_decoration;
*/

    char * d_tcl_script_dir;

    // VRPN stuff

    long d_myId;

    // general messages

    long d_SetRegionNM_type;  // from client
    long d_ScanTo_type;
    long d_ZagTo_type;
    long d_SetScanStyle_type;
    long d_SetSlowScan_type;
    long d_SetStdDelay_type;
    long d_SetStPtDelay_type;
    long d_SetRelax_type;
    long d_RecordResistance_type;
    long d_SetStdDevParams_type;
    long d_SetScanWindow_type;
    long d_ResumeWindowScan_type;
    long d_SetGridSize_type;
    long d_SetOhmmeterSampleRate_type;
    long d_EnableAmp_type;
    long d_DisableAmp_type;
    long d_EnableVoltsource_type;
    long d_DisableVoltsource_type;
    long d_SetRateNM_type;
    long d_SetMaxMove_type;
    long d_SetModForce_type;
    long d_DrawSharpLine_type;
    long d_DrawSweepLine_type;
    long d_DrawSweepArc_type;
    long d_GetNewPointDatasets_type;
    long d_GetNewScanDatasets_type;
    long d_Echo_type;
    long d_Shutdown_type;
    long d_QueryScanRange_type;
    long d_QueryStdDevParams_type;
    long d_QueryPulseParams_type;

    long d_VoltsourceEnabled_type;  // from server
    long d_VoltsourceDisabled_type;
    long d_AmpEnabled_type;
    long d_AmpDisabled_type;
    long d_StartingToRelax_type;
    long d_RelaxSet_type;
    long d_StdDevParameters_type;
    long d_WindowLineData_type;
    long d_WindowScanNM_type;
    long d_WindowBackscanNM_type;
    long d_PointResultNM_type;
    long d_PointResultData_type;
    long d_BottomPunchResultData_type;
    long d_TopPunchResultData_type;
      // PointResultData, BottomPunchResultData, and TopPunchResultData
      // are all handled by encode_ResultData() and decode_ResultData()
    long d_ZigResultNM_type;
    long d_BluntResultNM_type;
      // ZigResultNM and BluntResultNM are both handled
      // by encode_ResultNM() and decode_ResultNM()
    long d_ScanRange_type;
    long d_SetRegionCompleted_type;
    long d_SetRegionClipped_type;
    long d_ResistanceFailure_type;
    long d_Resistance_type;
    long d_Resistance2_type;
    long d_ReportSlowScan_type;
    long d_ScanParameters_type;
    long d_HelloMessage_type;
    long d_ClientHello_type;
    long d_ScanDataset_type;
    long d_PointDataset_type;
    long d_PidParameters_type;
    long d_ScanrateParameter_type;
    long d_ReportGridSize_type;
    long d_ServerPacketTimestamp_type;
    long d_TopoFileHeader_type;
    long d_ForceCurveData_type;

    // messages for Michele Clark's experiments
    long d_RecvTimestamp_type;
    long d_FakeSendTimestamp_type;
    long d_UdpSeqNum_type;

    // AFM-ish

    long d_EnterTappingMode_type;  // from client
    long d_EnterContactMode_type;
    long d_EnterSewingStyle_type;
    long d_SetContactForce_type;
    long d_QueryContactForce_type;
    long d_EnterSpectroscopyMode_type;

    long d_ForceSet_type;  // from server
    long d_ForceSetFailure_type;
    long d_ForceParameters_type;
    long d_ModForceSet_type;
    long d_ImgForceSet_type;
    long d_ModForceSetFailure_type;
    long d_ImgForceSetFailure_type;
    long d_ImgSet_type;
    long d_ModSet_type;
    long d_InModMode_type;
    long d_InImgMode_type;
    long d_InModModeT_type;
    long d_InImgModeT_type;
    long d_InTappingMode_type;
    long d_InContactMode_type;
    long d_InSewingStyle_type;
    long d_InSpectroscopyMode_type;

    long d_BaseModParameters_type;  // from client to itself
    long d_ForceSettings_type;

    // STM-ish

    long d_SampleApproach_type;  // from client
    long d_SetBias_type;
    long d_SampleApproachNM_type;
    long d_SetPulsePeak_type;
    long d_SetPulseDuration_type;
    long d_PulsePoint_type;
    long d_PulsePointNM_type;

    long d_TunnellingAttained_type;  // from server
    long d_TunnellingAttainedNM_type;
    long d_TunnellingFailure_type;
    long d_ApproachComplete_type;
    long d_PulseCompleted_type;
    long d_PulseFailure_type;
    long d_PulseParameters_type;
    long d_PulseCompletedNM_type;
    long d_PulseFailureNM_type;




    // encode_ functions take as parameters all the data carried in
    // the message.  They allocate a char array and marshall the message's
    // data in it, returning its length in their first argument (long * len).
    // On error, these functions return a NULL pointer and a 0 length.
    // It is the caller's responsibility to delete [] the array returned
    // after using it.

    // decode_ functions take a pointer to the buffer to unmarshall
    // and variables to unmarshall into.
    // They advance this pointer past the end of the unmarshalled data.
    // Passing a NULL into these routines is an error.
    // They return 0 on success, -1 on error.

    // Variable-length messages with a regular repeating format
    // (e.g. WindowLineData, ScanDatasets) have two decode_ functions.
    // The first reads the fixed header, which includes a count of the
    // number of records that follow.  The second reads one record.


    char * encode_SetRegionNM (long * len,
                  float minx, float miny, float maxx, float maxy);
    long decode_SetRegionNM (const char ** buf,
               float * minx, float * miny, float * maxx, float * maxy);
    char * encode_ScanTo (long * len, float x, float y);
    long decode_ScanTo (const char ** buf, float * x, float * y);
    char * encode_ZagTo (long * len, float x, float y, float yaw,
                  float sweepWidth, float regionDiag);
    long decode_ZagTo (const char ** buf, float * x, float * y, float * yaw,
               float * sweepWidth, float * regionDiag);
    char * encode_SetScanStyle (long * len, long value);
    long decode_SetScanStyle (const char ** buf, long * value);
    char * encode_SetSlowScan (long * len, long value);
    long decode_SetSlowScan (const char ** buf, long * value);
    char * encode_SetStdDelay (long * len, long delay);
    long decode_SetStdDelay (const char ** buf, long * delay);
    char * encode_SetStPtDelay (long * len, long delay);
    long decode_SetStPtDelay (const char ** buf, long * delay);
    char * encode_SetRelax (long * len, long min, long sep);
    long decode_SetRelax (const char ** buf, long * min, long * sep);
    char * encode_RecordResistance (long * len, long meter, struct timeval time,
                  float resistance, float v, float r, float f);
    long decode_RecordResistance (const char ** buf, long * meter,
               struct timeval * time, float * resistance, float * v,
               float * r, float * f);
    char * encode_SetStdDevParams (long * len, long samples, float freq);
    long decode_SetStdDevParams (const char ** buf,
               long * samples, float * freq);
    char * encode_SetScanWindow (long * len,
                  long minx, long miny, long maxx, long maxy);
    long decode_SetScanWindow (const char ** buf,
               long * minx, long * miny, long * maxx, long * maxy);
    char * encode_SetGridSize (long * len, long x, long y);
    long decode_SetGridSize (const char ** buf, long * x, long * y);
    char * encode_SetOhmmeterSampleRate (long * len, long which, long rate);
    long decode_SetOhmmeterSampleRate (const char ** buf,
               long * which, long * rate);
    char * encode_EnableAmp (long * len,
                  long which, float offset, float percentOffset, long gain);
    long decode_EnableAmp (const char ** buf,
               long * which, float * offset, float * percentOffset,
               long * gain);
    char * encode_DisableAmp (long * len, long which);
    long decode_DisableAmp (const char ** buf, long * which);
    char * encode_EnableVoltsource (long * len, long which, float voltage);
    long decode_EnableVoltsource (const char ** buf,
               long * which, float * voltage);
    char * encode_DisableVoltsource (long * len, long which);
    long decode_DisableVoltsource (const char ** buf, long * which);
    char * encode_SetRateNM (long * len, float rate);
    long decode_SetRateNM (const char ** buf, float * rate);
    char * encode_SetMaxMove (long * len, float distance);
    long decode_SetMaxMove (const char ** buf, float * distance);
    char * encode_SetModForce (int * len, float newforce, float min, float max);
    int decode_SetModForce (const char ** buf, float * distance, float * min, float * max);

    char * encode_DrawSharpLine (long * len,
                  float startx, float starty, float endx, float endy,
                  float stepSize);
    long decode_DrawSharpLine (const char ** buf,
               float * startx, float * starty, float * endx, float * endy,
               float * stepSize);
    char * encode_DrawSweepLine (long * len,
                  float startx, float starty, float startYaw,
                  float startSweepWidth, float endx, float endy, float endYaw,
                  float endSweepWidth, float stepSize);
    long decode_DrawSweepLine (const char ** buf,
               float * startx, float * starty, float * startYaw,
               float * startSweepWidth, float * endx, float * endy,
               float * endYaw, float * endSweepWidth, float * stepSize);
    char * encode_DrawSweepArc (long * len,
                  float x, float y, float startAngle, float startSweepWidth,
                  float endAngle, float endSweepWidth, float stepSize);
    long decode_DrawSweepArc (const char ** buf,
               float * x, float * y, float * startAngle,
               float * startSweepWidth, float * endAngle,
               float * endSweepWidth, float * stepSize);
/*  Tiger       moved it to nmm_MicroscopeRemote
    char * encode_GetNewPointDatasets (long * len, const Tclvar_checklist *);
*/
    long decode_GetNewPointDatasetHeader (const char ** buf, long * numSets);
    long decode_GetNewPointDataset (const char ** buf,
               char * name, long * numSamples);
/*  Tiger       moved it to nmm_MicroscopeRemote
    char * encode_GetNewScanDatasets (long * len, const Tclvar_checklist *);
*/
    long decode_GetNewScanDatasetHeader (const char ** buf, long * numSets);
    long decode_GetNewScanDataset (const char ** buf, char * name);
    char * encode_MarkModify (long * len);
    char * encode_MarkImage (long * len);


    char * encode_VoltsourceEnabled (long * len, long, float);
    long decode_VoltsourceEnabled (const char ** buf, long *, float *);
    char * encode_VoltsourceDisabled (long * len, long);
    long decode_VoltsourceDisabled (const char ** buf, long *);
    char * encode_AmpEnabled (long * len, long, float, float, long);
    long decode_AmpEnabled (const char ** buf, long *, float *, float *, long *);
    char * encode_AmpDisabled (long * len, long);
    long decode_AmpDisabled (const char ** buf, long *);
    char * encode_StartingToRelax (long * len, long, long);
    long decode_StartingToRelax (const char ** buf, long *, long *);
    char * encode_RelaxSet (long * len, long, long);
    long decode_RelaxSet (const char ** buf, long *, long *);
    char * encode_StdDevParameters (long * len, long, float);
    long decode_StdDevParameters (const char ** buf, long *, float *);
    char * encode_WindowLineData (long * len, long, long, long, long,
                                  long, long, long, long, float **); // Changed by Tiger also by Jake Kitchener
    long decode_WindowLineDataHeader (const char ** buf, long *,
                                      long *, long *, long *,
                                      long *, long *, long *, long *);
    long decode_WindowLineDataField (const char ** buf, 
                                     long, float *);
    char * encode_WindowScanNM (long * len, long, long, long, long, float,
                                float);
    long decode_WindowScanNM (const char ** buf, long *, long *, long *, long *,
                              float *, float *);
    char * encode_WindowBackscanNM (long * len, long, long, long, long, float,
                                    float);
    long decode_WindowBackscanNM (const char ** buf, long *, long *, long *,
                                  long *, float *, float *);
    char * encode_PointResultNM (long * len, float, float, long, long, float,
                                 float);
    long decode_PointResultNM (const char ** buf, float *, float *, long *,
                               long *, float *, float *);
    char * encode_ResultData (long * len, float, float, long, long, long,
                              float *);
    long decode_ResultData (const char ** buf, float *, float *, long *,
                            long *, long *, float *);
    char * encode_ResultNM (long * len, float, float, long, long, float, float,
                            float, float);
    long decode_ResultNM (const char ** buf, float *, float *, long *, long *,
                          float *, float *, float *, float *);
    char * encode_ScanRange (long * len, float, float, float, float, float,
                             float);
    long decode_ScanRange (const char ** buf, float *, float *, float *,
                           float *, float *, float *);
    char * encode_SetRegionC (long * len, float, float, float, float);
    long decode_SetRegionC (const char ** buf, float *, float *,
                            float *, float *);
    char * encode_ResistanceFailure (long * len, long);
    long decode_ResistanceFailure (const char ** buf, long *);
    char * encode_Resistance (long * len, long, long, long, float);
    long decode_Resistance (const char ** buf, long *, long *, long *, float *);
    char * encode_Resistance2 (long * len, long, long, long, float, float, float,
                               float);
    long decode_Resistance2 (const char ** buf, long *, long *, long *, float *,
                             float *, float *, float *);
    char * encode_ReportSlowScan (long * len, long);
    long decode_ReportSlowScan (const char ** buf, long *);
    char * encode_ScanParameters (long * len, char *);  // TODO
    long decode_ScanParameters (const char ** buf, long * length,
                                char ** buffer);
      // Allocates *length characters in *buffer and fills it in with
      // the scan parameters.  It is the caller's responsibility to delete [].

    char * encode_HelloMessage (long * len, char *, char *, long, long);
    long decode_HelloMessage (const char ** buf, char *, char *, long *,
                              long *);
    char * encode_ClientHello (long * len, char *, char *, long, long);
    long decode_ClientHello (const char ** buf, char *, char *, long *,
                             long *);
    long decode_ScanDatasetHeader (const char ** buf, long *);
    long decode_ScanDataset (const char ** buf, char *, char *, float *,
                             float *);
    long decode_PointDatasetHeader (const char ** buf, long *);
    long decode_PointDataset (const char ** buf, char *, char *, long *,
                              float *, float *);
    char * encode_PidParameters (long * len, float, float, float);
    long decode_PidParameters (const char ** buf, float *, float *,
                float *);
    char * encode_ScanrateParameter (long * len, float);
    long decode_ScanrateParameter (const char ** buf, float *);
    char * encode_ReportGridSize (long * len, long, long);
    long decode_ReportGridSize (const char ** buf, long *, long *);
    char * encode_ServerPacketTimestamp (long * len, long, long);
    long decode_ServerPacketTimestamp (const char ** buf, long *, long *);
// Implemented by Tiger
    char * encode_TopoFileHeader (long * len, char * buf, long size);
// Tiger
    long decode_TopoFileHeader (const char ** buf, long *, char **);
      // Allocates *length characters in *buffer and fills it in with
      // the scan parameters.  It is the caller's responsibility to delete [].

    // similar structure to WindowLineData: num_points = reports,
    //                              num_halfcycles = fields
    char * encode_ForceCurveData (long * len, float x, float y, long num_points,
                                long num_halfcycles, long sec, long usec,
                                float *z, float **data);
    long decode_ForceCurveDataHeader (const char ** buf, float *x, float *y,
                                long *num_points, long *num_halfcycles, 
                                long *sec, long *usec);
    long decode_ForceCurveDataSingleLevel (const char ** buf,
                                long num_halfcycles, float *z, float * data);

    // messages for Michele Clark's experiments
    char * encode_RecvTimestamp (long * len, struct timeval);
    long decode_RecvTimestamp (const char ** buf, struct timeval *);
    char * encode_FakeSendTimestamp (long * len, struct timeval);
    long decode_FakeSendTimestamp (const char ** buf, struct timeval *);
    char * encode_UdpSeqNum (long * len, long);
    long decode_UdpSeqNum (const char ** buf, long *);


    // AFM-ish

    char * encode_EnterTappingMode (long * len, float, float, float,
                                          float, float);
    long decode_EnterTappingMode (const char ** buf, float *, float *,
                                  float *, float *, float *);
    char * encode_EnterContactMode (long * len, float, float, float,
                                          float);
    long decode_EnterContactMode (const char ** buf, float *, float *,
                                  float *, float *);
    char * encode_EnterSewingStyle (long * len, float, float, float,
                                          float, float, float, float);
    long decode_EnterSewingStyle (const char ** buf, float *,float *,float *,
                                  float *, float *, float *,
                                  float *);

    char * encode_EnterSpectroscopyMode (long * len, float, float, float, float,
                        float, float, float, long, long,float,float,float,float,
                        long, float, float, float);
    long decode_EnterSpectroscopyMode (const char ** buf,float *,float *,float *,
                        float *, float *, float *, float *, long *, long *,
                        float *, float *, float *, float *,
                        long *, float *, float *, float *);

    char * encode_InTappingMode (long * len, float, float, float,
                                float, float);
    long decode_InTappingMode (const char ** buf, float *, float *, float *,
                               float *, float *);
    char * encode_InContactMode (long * len, float, float, float,
                                float);
    long decode_InContactMode (const char ** buf, float *, float *, float *,
                               float *);
    char * encode_InSewingStyle (long * len, float, float, float,
                                float, float, float,
                                float);
    long decode_InSewingStyle (const char ** buf, float *, float *, float *,
                              float *, float *, float *, float *);
    char * encode_InSpectroscopyMode (long * len,float,float,float,float,float,
                                float, float, long, long,float,float,float,float,
                                long, float, float,float);
    long decode_InSpectroscopyMode (const char ** buf, 
                                float *, float *, float *, float *,
                                float *, float *, float *, long *, long *,
                                float *, float *, float *, float *,
                                long *, float *, float *, float *);
    char * encode_ForceParameters (long * len, long, float);
    long decode_ForceParameters (const char ** buf, long *, float *);
    char * encode_BaseModParameters (long * len, float, float);
    long decode_BaseModParameters (const char ** buf, float *, float *);
    char * encode_ForceSettings (long * len, float, float, float);
    long decode_ForceSettings (const char ** buf, float *, float *, float *);
    char * encode_InModModeT (long * len, long, long);
    long decode_InModModeT (const char ** buf, long *, long *);
    char * encode_InImgModeT (long * len, long, long);
    long decode_InImgModeT (const char ** buf, long *, long *);
    char * encode_ModForceSet (long * len, float);
    long decode_ModForceSet (const char ** buf, float *);
    char * encode_ImgForceSet (long * len, float);
    long decode_ImgForceSet (const char ** buf, float *);
    char * encode_ModSet (long * len, long, float, float, float);
    long decode_ModSet (const char ** buf, long *, float *, float *, float *);
    char * encode_ImgSet (long * len, long, float, float, float);
    long decode_ImgSet (const char ** buf, long *, float *, float *, float *);
    char * encode_ForceSet (long * len, float);
    long decode_ForceSet (const char ** buf, float *);
    char * encode_ForceSetFailure (long * len, float);
    long decode_ForceSetFailure (const char ** buf, float *);


    // STM-ish

    char * encode_SampleApproach (long * len, float);
    long decode_SampleApproach (const char ** buf, float *);
    char * encode_SetBias (long * len, float);
    long decode_SetBias (const char ** buf, float *);
    char * encode_SampleApproachNM (long * len, float);
    long decode_SampleApproachNM (const char ** buf, float *);
    char * encode_SetPulsePeak (long * len, float);
    long decode_SetPulsePeak (const char ** buf, float *);
    char * encode_SetPulseDuration (long * len, float);
    long decode_SetPulseDuration (const char ** buf, float *);
    char * encode_PulsePoint (long * len, float, float);
    long decode_PulsePoint (const char ** buf, float *, float *);
    char * encode_PulsePointNM (long * len, float, float);
    long decode_PulsePointNM (const char ** buf, float *, float *);

    char * encode_PulseParameters (long * len, long, float, float, float);
    long decode_PulseParameters (const char ** buf, long *, float *, float *,
                               float *);
    char * encode_PulseCompletedNM (long * len, float, float);
    long decode_PulseCompletedNM (const char ** buf, float *, float *);
    char * encode_PulseFailureNM (long * len, float, float);
    long decode_PulseFailureNM (const char ** buf, float *, float *);
    char * encode_PulseCompleted (long * len, float, float);
    long decode_PulseCompleted (const char ** buf, float *, float *);
    char * encode_PulseFailure (long * len, float, float);
    long decode_PulseFailure (const char ** buf, float *, float *);
    char * encode_TunnellingAttained (long * len, float);
    long decode_TunnellingAttained (const char ** buf, float *);
    char * encode_TunnellingAttainedNM (long * len, float);
    long decode_TunnellingAttainedNM (const char ** buf, float *);

    long dispatchMessage (long len, const char * buf, long type);
      // packs the message reliably and then deletes [] buf




};


#endif  // NMM_MICROSCOPE_H