#ifndef RcdReaderBin_HH
#define RcdReaderBin_HH

#include <string>

#include "RcdReader.hh"


class RcdReaderBin : public RcdReader {

public:
  RcdReaderBin();
  virtual ~RcdReaderBin();

  bool open(const std::string &file);
  bool read(RcdRecord &r);
  bool close();
  
private:
  void reset();

  int _fileDescriptor;
};


#ifdef CALICE_DAQ_ICC

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <iostream>

#ifdef DESY_DCACHE
#include "dcap.h" // dCache
#endif

#include "RcdReader.hh"


RcdReaderBin::RcdReaderBin() : _fileDescriptor(-1) {
}

RcdReaderBin::~RcdReaderBin() {
  close();
}

bool RcdReaderBin::open(const std::string &file) {
  if(_fileDescriptor>=0) close();
  reset();

  _fileName=file+".bin";
 
#ifdef DESY_DCACHE
  if(_printLevel>0) {
    std::cout << "RcdReaderBin::open()   Staged file "
	      << _fileName << std::endl;
  }

  _fileDescriptor=dc_open(_fileName.c_str(),O_RDONLY);
#else
  _fileDescriptor= ::open(_fileName.c_str(),O_RDONLY);
#endif
  
  if(_fileDescriptor<0) {
    std::cerr << "RcdReaderBin::open()   Error opening file "
	      << _fileName << "  " << strerror(errno)
	      << std::endl << std::flush;
    reset();
    return false;
  }
  
  if(_printLevel>0) {
    std::cout << "RcdReaderBin::open()   Opened file "
	      << _fileName << std::endl;
  }

  _isOpen=true;

  return true;
}

bool RcdReaderBin::read(RcdRecord &r) {
  if(_fileDescriptor<0) return false;
  
  int n(0);
  
#ifdef DESY_DCACHE
  n=dc_read(_fileDescriptor,&r,sizeof(RcdRecord));
#else
  n= ::read(_fileDescriptor,&r,sizeof(RcdRecord));
#endif

  if(n<=0) {
    if(_printLevel>1) {
      std::cout << "RcdReaderBin::read()   Expected end-of-file"
		<< std::endl;
    }
    return false;
  }
  
  _numberOfBytes+=sizeof(RcdRecord);
  
  if(r.numberOfWords()>100000) {
    std::cerr << "RcdReaderBin::read()   Too many words in record "
	      << r.numberOfWords() << " > 100000" << std::endl <<std::flush;
    return false;
  }

  if(r.numberOfWords()>0) {

#ifdef DESY_DCACHE
    n=dc_read(_fileDescriptor,(&r)+1,4*r.numberOfWords());
#else
    n= ::read(_fileDescriptor,(&r)+1,4*r.numberOfWords());
#endif

    if(n<=0) {
      std::cerr << "RcdReaderBin::read()   Unexpected end-of-file "
		<< "  " << strerror(errno) << std::endl << std::flush;
      return false;
    }

    _numberOfBytes+=4*r.numberOfWords();
  }
  
  return true;
}

bool RcdReaderBin::close() {
  if(_fileDescriptor<0) {
    reset();
    return false;
  }

#ifdef DESY_DCACHE
  if(dc_close(_fileDescriptor)<0) {
#else
  if( ::close(_fileDescriptor)<0) {
#endif

    std::cerr << "RcdReaderBin::close()  Error closing file "
	      << _fileName << "  " << strerror(errno)
	      << std::endl << std::flush;
    reset();
    return false;
  }
  
  if(_printLevel>0) {
    std::cout << "RcdReaderBin::close()  Closed file " << _fileName;
    if(_printLevel>1) std::cout << " after reading "
				<< _numberOfBytes << " bytes";
    std::cout << std::endl;
  }

  reset();
  return true;
}

void RcdReaderBin::reset() {
  RcdIoBase::reset();
  _fileDescriptor=-1;
}
  
#endif
#endif
