#ifndef RcdRecord_HH
#define RcdRecord_HH

#include <string>
#include <iostream>

#include "RcdHeader.hh"


class RcdRecord : public RcdHeader {

public:
  RcdRecord();
  RcdRecord(const RcdHeader &h);
  RcdRecord(const RcdRecord &b);

  void operator=(const RcdHeader &h);
  void operator=(const RcdRecord &b);

  void deleteData();
  void initialise(RcdHeader::RecordType t);

  unsigned numberOfWords() const;
  unsigned totalNumberOfBytes() const;

  const unsigned* data() const;
  unsigned* data();

  const unsigned* newData() const;
  unsigned* newData();

  unsigned operator[](unsigned n) const;

  void extend(unsigned d);
  void extend(unsigned n, const unsigned *p);

  std::ostream& print(std::ostream &o, std::string s="") const;


private:
  bool mergeRecord(const RcdRecord* r);


protected:
  unsigned _numberOfWords;
};


#ifdef CALICE_DAQ_ICC

#include <cstring>
#include <iomanip>

// record/inc/utl
#include "UtlPrintHex.hh"

RcdRecord::RcdRecord() : RcdHeader(), _numberOfWords(0) {
}

RcdRecord::RcdRecord(const RcdHeader &h) : RcdHeader(h), _numberOfWords(0) {
}

RcdRecord::RcdRecord(const RcdRecord &b) {
  memcpy(this,&b,b.totalNumberOfBytes());
}

void RcdRecord::operator=(const RcdHeader &h) {
  memcpy(this,&h,sizeof(RcdHeader));
  _numberOfWords=0;
}

void RcdRecord::operator=(const RcdRecord &b) {
  memcpy(this,&b,b.totalNumberOfBytes());
}

void RcdRecord::deleteData() {
  _numberOfWords=0;
}

void RcdRecord::initialise(RcdHeader::RecordType t) {
  RcdHeader::initialise(t);
  _numberOfWords=0;
}

unsigned RcdRecord::numberOfWords() const {
  return _numberOfWords;
}

unsigned RcdRecord::totalNumberOfBytes() const {
  return sizeof(RcdRecord)+_numberOfWords*sizeof(unsigned);
}

const unsigned* RcdRecord::data() const {
  return &_numberOfWords+1;
}

unsigned* RcdRecord::data() {
  return &_numberOfWords+1;
}

const unsigned* RcdRecord::newData() const {
  return &_numberOfWords+1+_numberOfWords;
}

unsigned* RcdRecord::newData() {
  return &_numberOfWords+1+_numberOfWords;
}

unsigned RcdRecord::operator[](unsigned n) const {
  if(n>_numberOfWords) return 0;
  return *(&_numberOfWords+1+n);
}

void RcdRecord::extend(unsigned d) {
  *(newData())=d;
  _numberOfWords++;
}

void RcdRecord::extend(unsigned n, const unsigned *p) {
  if(p!=0) memcpy(newData(),p,n*sizeof(unsigned));
  _numberOfWords+=n;
}

std::ostream& RcdRecord::print(std::ostream &o, std::string s) const {
  o << s << "RcdRecord::print()" << std::endl;
  RcdHeader::print(o,s+" ");
  
  o << s << " Data bytes stored "
    << totalNumberOfBytes()-sizeof(RcdRecord)
    << ", total bytes " << totalNumberOfBytes() << std::endl;
  
  o << s << " Number of words = " << _numberOfWords << std::endl;
  for(unsigned i(0);i<_numberOfWords;i++) {
    o << s << "  Word " << std::setw(5) << i << " = "
      << printHex(*(&_numberOfWords+i+1)) << std::endl;
  }
  
  return o;
}

bool RcdRecord::mergeRecord(const RcdRecord* r) {
  if(r==0) return false;
  
  RcdHeader *thisHeader(this);
  const RcdHeader *thatHeader(r);
  if(*thisHeader!=*thatHeader) return false;
  
  memcpy(data()+_numberOfWords,r->data(),4*r->_numberOfWords);
  
  return true;
}

#endif
#endif
