#ifndef HEPHBOOKNTUPLE_H
#define HEPHBOOKNTUPLE_H

// ----------------------------------------------------------------------
//
// HepHBookNtuple.h - class declaration for HBook n-tuple
//
// HepHBookNtuple is the implementation of the HBook n-tuple
// It is derived from HepNtuple (the generic interface).
// It is mainly a C++ wrapper around the CERNlib HBook
// Fortran histogramming libraries.
//
// No HepHBookNtuple objects are ever directly
// instantiated by the programmer. When creating new HepNtuple* objects,
// the manager is in charge of creating the appropriate HepHBook object.
//
// To use generate HBook n-tuple, HepHBookFileManager must be used:
//
//   int lunit = 10;
//   HepFileManager* m = new HepHBookFileManager("filename.rz", lunit);
//    :
//    :
//   HepNtuple& h(m->newHepNtuple("Title"));
//   [define HepNtuple]
//    :
//   [gather data]
//    :
//   h->capture();
//
//
// Note that the constructor can take an ID number which is used by
// the HBook implementation of HepNtuple. If omitted, the ID number is
// generated automatically (which is recommended). The ID number is
// available through the id() method.
//
//
// History:
//   18-Jul-1997  Philippe Canal Bare Creation

//
// ----------------------------------------------------------------------


#ifndef HEPHBOOKFILEMANAGER_H
  #include "HepTuple/HepHBookFileManager.h"
#endif

#ifndef HEPTUPLE_H
  #include "HepTuple/HepNtuple.h"
#endif


ZM_BEGIN_NAMESPACE( zmht )	/*  namespace zmht  {  */


class HepHBookNtuple : public HepNtuple  {

  friend class HepHBookFileManager;

protected:

  // create a 1D histogram with the given title and binning
  HepHBookNtuple(
    HepHBookFileManager * manager
  , const std::string& title
  , const int id_req = 0
  );

  // Used for dummy construction ...
  // the object is then not valid ...
  HepHBookNtuple( );                           // default constructor

  // Silence g++ complaints about various functions never being called
  void silenceCompiler();


public:

  virtual ~HepHBookNtuple();

  // clone an existing ntuple
  HepHBookNtuple(
    HepNtuple *   original
  , const std::string& title
  , const int     id_req = 0
  );
  virtual bool isNameAvailable ( const std::string& nameTag) const;
  virtual const TupleNameTag& parseNameTag ( TupleNameTag& what,
					     const std::string& nameTag,
					     bool WithIndices = false) const;

protected:

  virtual bool isRowWiseEnabled() const;
  virtual bool isColumnWiseEnabled() const;
  virtual bool isBlockWiseEnabled() const;
  virtual bool isDiskResidentEnabled() const;
  virtual bool isMemResidentEnabled() const;
  virtual bool isSharedMemoryEnabled() const;
  virtual bool isNwbuffEnabled(int nwbuff) const;
  virtual bool isBuffLimitEnabled(int limit) const;
  virtual bool isDemandBuffersEnabled() const;
  virtual bool isCircularBufferEnabled() const;
  virtual bool isCaseSensitive() const;

  // These methods tell if a manager can handle a certain type in
  // the given block.
  virtual bool isTypeEnabled(ColumnData_t type,Block *bk);
  virtual bool isTypeEnabled(ColumnData_t type);

  virtual bool setStorageGeometry(StorageGeometryName newStrategy);
  // override this function to prevent change of storage strategy
  // after actual creation of the HBook ntuple.

  virtual bool setStorageLocation(unsigned char newLocation);
  // override this function to prevent change of storage location
  // after actual creation of the HBook ntuple.

  virtual bool setNwbuffValue(int nwbuff);
  // override this function to do the actual HBook setting necessary
  // NOTE: the change is NOT local to this NTuple !!

  virtual bool setBuffLimitValue(int limit);
  // over-ride this function to do the actual hbook setting.

  virtual bool book();
  // this method should implement the booking the ntuple parts

  virtual bool bookRowWise();
  virtual bool bookColumnWise();

  virtual bool storeWholeRow();
  virtual bool storeSingleBlock(Block* bk);
  // Instruct the manager to store the row/block

  virtual int readWholeRow(int irow);
  virtual int readWholeBlock(Block* bk, int irow);
  virtual int readSingleColumn(Column* col, int irow);
  virtual int readSingleColumn(Column* col, const std::string& indices, 
			       int irow, void * val);
  virtual int readSingleColumn(Column* col, int irow, void * val);
  // Instruct the manager to read from file/memory into the destination
  // variable of all the columns of repectively the row, block, single column
  // ALL the listed columns are expected to have destination variables
  // (i,e. get the value at an address and send it to col->set(void *addr);

  virtual int readWholeColumn(Column* col, const std::string& indices, 
			      int start_row, int nrows, 
			      char * val, std::string::size_type size);
  virtual int readWholeColumn(Column* col,  
			      int start_row, int nrows, 
			      char * val, std::string::size_type size);
  // Instruct the manager to read a whole column and store it into val
  // which is assume to be array of the same type as the column and of size
  // nrows.  This function are called from bulkReadColumn
  // The manager independent implementation loop over the equivalent 
  // readSingleColumn function

  // function to help caching of reading calls

  Float4* readRWNrow(int irow);

  void setCwnColumnRead(Column* col, void* addr = NULL);
  // This function makes the needed set-up to read
  // a single column from a Column Wise Ntuple

  bool restoreNtuple();
  // This function restores the details of the internal structure
  // for an existing ntuple

  bool setCwnAddresses();
  // This function makes the needed set-up to an existing
  // Column Wise Ntuple

private:

  // forbidden operations, hence private:
  //HepHBookNtuple( );              // default constructor
  HepHBookNtuple( const HepHBookNtuple & );   // copy constructor
  HepHBookNtuple & operator=( const HepHBookNtuple & );  // assignment

  int _nColumnCreated;
  // Number of column created in a row wise N-Tuple

  // data to help caching of reading calls

  Float4* _lastRwnArray;
  void* _lastArrayRead;
  int _lastRowRead;
  bool _addrSetUp;

};  // HepHBookNtuple


ZM_END_NAMESPACE( zmht )	/*  }  // namespace zmht  */


#endif  // HEPHBOOKNTUPLE_H
