#ifndef _CDEV_DIRECTORY_H
#define _CDEV_DIRECTORY_H

#include <cdevSpec.h>
#include <cdevData.h>
#include <cdevCallback.h>
#include <cdevDevice.h>

class cdevDirectoryTable;
class StringHash;

class CDEV_CLASS_SPEC cdevDirectory : public cdevDevice
{
public:
  cdevDirectory(cdevSystem &system=cdevSystem::defaultSystem());
  ~cdevDirectory(void);
  
  int addNameSvc(cdevDevice *svc);
  int removeNameSvc(cdevDevice *svc);

  int send(char *msg, cdevData &data, cdevData &result);
  int send(char *msg, cdevData *data, cdevData &result);
  int send(char *msg, cdevData &data, cdevData *result);
  int send(char *msg, cdevData *data, cdevData *result);
  
  int sendNoBlock(char *msg, cdevData &out, cdevData &result);
  int sendNoBlock(char *msg, cdevData *out, cdevData &result);
  int sendNoBlock(char *msg, cdevData &out, cdevData *result);
  int sendNoBlock(char *msg, cdevData *out, cdevData *result);
  
  int sendCallback(char *msg, cdevData &out, cdevCallback &callback);
  int sendCallback(char *msg, cdevData *out, cdevCallback &callback);
  
  cdevRequestObject *getRequestObject  (char *msg);
  int                getRequestObject  (char *msg, cdevRequestObject* &reqobj);
  
  virtual const char *className(void) const { return "cdevDirectory"; }

private:
  typedef int (*QueryFunction)  ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );

  static int query              ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int queryClass         ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );  
  static int queryClasses       ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int queryCollection    ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int queryVerbs         ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int queryAttributes    ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int queryMessages      ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out ); 
  static int service            ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int resolveService     ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int serviceData        ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int resolveServiceData ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int validate           ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int update             ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );
  static int writeAscii         ( cdevDirectory &dir,
				 char * msg, cdevData *in, cdevData *out );
  static int writeBinary        ( cdevDirectory &dir, 
				 char * msg, cdevData *in, cdevData *out );

  class cdevDirectoryNode
    {
    public:
      cdevDirectoryNode ( cdevDevice * svc = NULL ) : next(NULL), device(svc) {}
      ~cdevDirectoryNode( void ) {}	
      cdevDirectoryNode * next;
      cdevDevice        * device;
    };
  
  cdevDirectoryNode        * node;
  class cdevDirectoryTable * table;
  class StringHash         * commandHash;
};

#endif
