//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
//      Channel Access Channel Monitoring Object
//
// Author:  Jie Chen
//
// Revision History:
//   caMonObj.h,v
// Revision 1.3  1998/03/05  18:49:12  chen
// fix a bug on context == 2 on property channels
//
// Revision 1.2  1996/09/18  14:46:49  chen
// Channel holds multiple monitor objects
//
// Revision 1.1  1995/10/03  19:58:08  chen
// channel monitoring class
//
//
//
#ifndef _CA_MON_OBJ_H
#define _CA_MON_OBJ_H

#include <cdevTranObj.h>

// epics stuff
#if !defined (_EPICS_3_12)
#define __STDC__
extern "C"{
#endif

#include <cadef.h>
#include <db_access.h>

#if !defined (_EPICS_3_12)
};
#undef __STDC__
#endif

// class caMonObj is a monitor object that is very similar to
// the cdevTranObj except no group information. It will be used
// in the case of monitoring a particular channel which the user 
// callback need to be around after the transaction object goes away.
// 
// each monitor object has unique request mask/type + evid information with
// multiple different callbacks

//====================================================================
//   connected channel monitoring data buffer
//         When a caChannel is connected, the caMonData will be created
//         to accept new data from remote IOC
//=====================================================================   
class caMonData
{
public:
  // constrcutor and destructor
  caMonData    (void);
  ~caMonData   (void);
  
  void                 *value;
  int                  *status;
  int                  *severity;
  cdev_TS_STAMP        *tstamp;
  int                  *precision;
  float                *disphi;
  float                *displo;
  float                *warnhi;
  float                *warnlo;
  float                *alrmhi;
  float                *alrmlo;
  float                *ctrlhi;
  float                *ctrllo;

private:
  // deny access to copy and assignment
  caMonData (const caMonData& data);
  caMonData& operator = (const caMonData& data);
};


class caMonObj;
class caChannel;

class caMonCbk
{
public:
  // constructor and destructor
  
  // just copy pointer for callback
  caMonCbk (cdevCallback* cbk, cdevData* out, caMonCbk* next = 0);
  // duplicate callback
  caMonCbk (cdevCallback& cbk, cdevData* out, caMonCbk* next = 0);

  ~caMonCbk (void);

  void enableCache  (void);
  void disableCache (void);

  const char* className (void) const {return "caMonCbk";}

  // data area
  cdevCallback* cbk_;
  cdevData*     out_;
  int           cached_;

  // pointer to next
  caMonCbk*     next_;

private:
  // denay access to copy and assignment operator
  caMonCbk (const caMonCbk& cbk);
  caMonCbk& operator = (const caMonCbk& cbk);
};


class caMonObj
{
public:
  // constructor and destructor
  caMonObj  (cdevTranObj& obj);

  // create new caMonObj with duplicated callback
  caMonObj  (const caMonObj& obj, cdevCallback* cbk, cdevData* out);  
  ~caMonObj (void);

  // check whether this monitor object has the same callback already
  // return 1: yes, return 0: no
  int hasSameCallback (cdevCallback& cbk);

  // add a new callback to the list
  // return 1: success, return 0: failed, already there
  int addCallback     (caMonCbk* cbk);

  // remove a callback from the list
  // if the callback has function 0 and usrarg 0, we will rmove everything
  // and stop monitoring. otherwise we will remove a single callback
  // return 1: success, 0: not found
  int removeCallback  (cdevCallback* cbk);

  // call all callbacks
  void callCallbacks  (int status, cdevRequestObject* req, cdevData& data);

  // call a single callback denoted by caMonCbk 'cbk'
  // this is used when one adds a callback which has the same context 
  // as this moinitor object
  void callCallback   (caMonCbk* cbk);

  // set monitor object information
  void setMonitorInfo (int tag, int status, caChannel* arg,
		       int type, int mask);

  // setup monitoring data buffers which point to various cdevData
  // object internal buffers
  static int setupMonitorBuffer (int tag, 
				 cdevData& data, 
				 caMonData& monData, 
				 int dataType);

  const char *className (void) const {return "caMonObj";}

  // pointer to transaction object
  cdevTranObj*      tobj_;

  // data area that is from transaction object
  cdevSystem        *system_;
  cdevRequestObject *reqObj_;

  // tag and callback status associated with this monitor object
  int               tag_;
  int               cbkStatus_;

  // request mask and type of this monitoring object
  int               reqMask_;
  int               reqType_;

  // user arg to remember which channel this monitor object belongs to
  caChannel*        channel_;

  // cached value
  cdevData          cache_;
  caMonData         data_;
  int               cacheInited_;
  

  // channel access event id
  evid              mEvId_;
  // number of callbacks
  int               count_;

  // head to list of caMonCbk s
  caMonCbk*         cbks_;

private:
  // deny access to copy and assignment

  caMonObj& operator = (const caMonObj&);
};

#endif
