#ifndef RcdIoSkt_HH
#define RcdIoSkt_HH

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

#include <iostream>

#include "RcdWriter.hh"
#include "DuplexSocket.hh"

class RcdIoSkt : public RcdIoBase {

public:
  RcdIoSkt() {
  }

  virtual ~RcdIoSkt() {
    close();
  }

  bool open(std::string host, unsigned port, unsigned tries) {
    _fileName=host;
    _socket=new DuplexSocket(host,port,tries);
    return open2();
  }

  bool open(unsigned port) {
    _fileName="listener";
    _socket=new DuplexSocket(port);
    return open2();
  }

  bool open2() {
    _readNumberOfBytes=0;
    _writeNumberOfBytes=0;

    if(_socket==0) {
      std::cerr << "RcdIoSkt::open()   Error opening socket "
		<< _fileName << std::endl;
      return false;
    }

    std::cout << "RcdIoSkt::open()   Opened socket "
	      << _fileName << std::endl;
    return true;
  }

  bool noDelay() {
    return _socket->noDelay();
  }

  bool read(RcdRecord &r) {
    if(_socket==0) return false;

    int n(0);
 
    n=_socket->recv((char*)&r,sizeof(RcdRecord));
    if(n<=0) {
      std::cout << "RcdIoSkt::read()   Expected end-of-file" << std::endl;
      return false;
    }
    _readNumberOfBytes+=sizeof(RcdRecord);

    if(r.numberOfWords()>0) {
      n=_socket->recv((char*)((&r)+1),4*r.numberOfWords());
      if(n<=0) {
        std::cerr << "RcdIoSkt::read()   Unexpected end-of-file ";
        perror(0);
        return false;
      }
      _readNumberOfBytes+=4*r.numberOfWords();
    }

    return true;
  }

  bool write(const RcdRecord &r) {
    if(_socket==0) return false;

    //if(r.totalNumberOfBytes()>48*1024) { // 2006 limit
    if(r.totalNumberOfBytes()>CALICE_DAQ_SIZE) { // 2007 limit
      std::cerr << "RcdIoSkt::write()  ERROR  Number of bytes to send = "
		<< r.totalNumberOfBytes() << " for record" << std::endl;
      r.RcdHeader::print(std::cerr) << std::endl;
    }

    int n(r.totalNumberOfBytes());
    if(!_socket->send((const char*)(&r),n)) {
      std::cerr << "RcdIoSkt::write()  Error writing to file; number of bytes written < "
	   << n << std::endl;
      perror(0);
      //_numberOfBytes+=n;
      return false;
    }

    _writeNumberOfBytes+=r.totalNumberOfBytes();

    return true;
  }

  bool close() {
    if(_socket==0) return false;

    delete _socket;
    std::cout << "RcdIoSkt::close()  Closed socket "
	      << _fileName << " after reading, writing "
	      << _readNumberOfBytes << ", " << _writeNumberOfBytes
	      << " bytes" << std::endl;

    _socket=0;
    _writeNumberOfBytes=0;
    _readNumberOfBytes=0;
    return true;
  }

  unsigned numberOfBytes(bool w=true) const {
    if(w) return _writeNumberOfBytes;
    else  return _readNumberOfBytes;
  }


private:
  DuplexSocket *_socket;
  std::string _fileName;
  unsigned _readNumberOfBytes;
  unsigned _writeNumberOfBytes;
};

#endif
