#ifndef SceSlowReadout_HH
#define SceSlowReadout_HH

#include <iostream>
#include <fstream>

// dual/inc/utl
#include "UtlPack.hh"

// dual/inc/rcd
#include "RcdUserRW.hh"
#include "RcdHeader.hh"

// dual/inc/sub
#include "SubInserter.hh"
#include "SubAccessor.hh"

// dual/inc/skt
#include "DuplexSocket.hh"


class SceSlowReadout : public RcdUserRW {

public:
  //  SceSlowReadout(std::string ipAddress="localhost",
  SceSlowReadout(std::string ipAddress="192.168.0.40", // FNAL
		 unsigned port=1201, unsigned tries=10) :
    RcdUserRW(), _socket(ipAddress.c_str(),port,tries) {

    std::cout << std::endl << "SceSlowReadout::ctor()  SOCKET ESTABLISHED" << std::endl << std::endl;
  }

  virtual ~SceSlowReadout() {
  }

  bool record(RcdRecord &r) {
    if(doPrint(r.recordType())) {
      std::cout << "SceSlowReadout::record()" << std::endl;
      r.RcdHeader::print(std::cout," ") << std::endl;
    }
    
    // Check record type
    if(r.recordType()==RcdHeader::startUp) {

      std::string recv;
      sendAndRecv("reset",recv);
      
      // Nothing to read back
    }
    
    // Slow readout
    if(r.recordType()==RcdHeader::slowReadout) {
      SubInserter inserter(r);
      
      std::string recv;
      sendAndRecv("temperature",recv);
      SceSlowTemperatureData y;
      assert(y.parse(recv));
      if(doPrint(r.recordType(),2)) y.print(std::cout) << std::endl;
      inserter.insert<SceSlowTemperatureData>(y);

      for(unsigned i(0);i<32;i++) {
	std::ostringstream sout;
	sout << "readout mod " << i+1;
	  
	sendAndRecv(sout.str(),recv);
	SceSlowReadoutData x;
	assert(x.parse(recv));
	if(doPrint(r.recordType(),2)) x.print(std::cout) << std::endl;
	inserter.insert<SceSlowReadoutData>(x);
      }
    }

    return true;
  }
  
  bool sendAndRecv(const std::string &s, std::string &r) {
    r.clear();

    //if(doPrint(r.recordType(),4))
    //  std::cout << " sendAndRecv()  std::string to send "
    //	<< s.size() << " bytes ==>" << s << "<==" << std::endl;

    std::string t("daqrequest "+s+'#');
    //if(doPrint(r.recordType(),5))
 std::cout << t << std::endl;

    if(!_socket.send(t.c_str(),t.size())) {
      std::cerr << "SceSlowReadout::sendAndRecv()  Error writing to socket;"
		<< " number of bytes written < " << s.size() << std::endl;
      perror(0);
      return false;
    }
    
    bool terminated(false);
    //bool terminated(true);
    char x;
    std::string h;
    //std::cout <<"Before receving part! " << terminated << std::endl;
     
    for(unsigned i(0);!terminated;i++) {
      int n(-1);
      //if(doPrint(r.recordType(),6)) std::cout << " sendAndRecv()  Waiting for byte " << i;
      n=_socket.recv(&x,1);
      //if(doPrint(r.recordType(),6)) std::cout << "...got byte " << i << std::endl;
      
      if(n!=1) {
	std::cerr << "SceSlowReadout::sendAndRecv()  Error reading from socket;"
		  << " number of bytes written = " << n << " < 1" << std::endl;
	perror(0);
	return false;
      }

      if(x=='#') terminated=true;
      else {
	if(i>10) r+=x;
	else     h+=x;
      }
    }

    //if(doPrint(r.recordType(),4))

      std::cout << " sendAndRecv()  std::string recv ed "
    	<< " header " << h.size()
    	<< " bytes ==>" << h << "<=="
    	<< ", message " << r.size()
    	<< " bytes ==>" << r << "<==" << std::endl;
    
    return true;
  }
    
private:
  DuplexSocket _socket;
};

#endif
