
#include <string>
#include <log4cxx/logger.h>
#include "NeutronDetectorReader.h"

using namespace pamela;
using namespace pamela::neutron;

static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("pamela.techmodel.neutron.NeutronDetectorReader"));

/**
 * Constructor. 
 */
NeutronDetectorReader::NeutronDetectorReader(void): 
  TechmodelAlgorithm(PacketType::Physics, "TechmodelNeutronDetectorReader") { 
  logger->debug(_T("Constructor"));
  neutronEvent = new NeutronEvent();
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string NeutronDetectorReader::GetVersionInfo(void) const {
  return 
    "$Header: /home/cvsmanager/yoda/techmodel/physics/NeutronDetectorReader.cpp,v 4.4 2005/05/28 10:44:13 kusanagi Exp $";
}

/**
 * Initialize the algorithm with a special run. This will initialize the
 * event reader routines for all packet types.
 * For definition the definition for Neutron detector data is located in the 
 * end of the physics packet.
 * More explicitely the neutronData is composed by 4 bytes;
 * a pattern 00 0F TR BK
 * where:
 * 00 0f is a fixed pattern
 * TR is the NeutronCounter for a trigger event
 * BK is the NeutronCounter beetween two trigger events
 */
void NeutronDetectorReader::Init(PamelaRun *run) {
  logger->debug(_T("Initialize"));
  SetInputStream(run);
  run->WriteSubPacket(this, &neutronEvent, neutronEvent->Class());
}

/**
 * Unpack the anticounter event from an input file.
 */
void NeutronDetectorReader::RunEvent(int EventNumber) {
  
}

/**
 * Unpack the NeutronDetector data event from the physical packet.
 */
void NeutronDetectorReader::RunEvent(int EventNumber, const char subData[], long int length) {
   NeutronRecord *rec;
   const int lenNeutronData = 12;
   //char *data = new char[lenght];
   //memcpy(data, subData, lenght);
   neutronEvent->Records->Clear();
   TClonesArray &recs = *(neutronEvent->Records);
   int offset;
   if (haveData(&*subData, length)){
        for (int i = 0; i < 3; i++){
            offset = lenNeutronData - 4*i;
            rec = new(recs[i]) NeutronRecord(); //aggiungo un nuovo NeutronRecord all'evento
            rec->trigPhysics = (UINT8)subData[length-offset];
            rec->upperBack   = (((UINT8)subData[length-offset+1])>>4);
            rec->bottomBack  = (((UINT8)subData[length-offset+1])&0x0F);
        }
        neutronEvent->unpackError = 0;
    } else {
        neutronEvent->unpackError = 1;
    }
}


bool NeutronDetectorReader::haveData(const char data[], long int length){
    bool ret = false;
    if (((UINT8)data[length - 1] == 0x0F)&&((UINT8)data[length - 5] == 0x0F)&&((UINT8)data[length - 9] == 0x0F) && 
        ((UINT8)data[length - 2] == 0x00)&&((UINT8)data[length - 6] == 0x00)&&((UINT8)data[length - 10] == 0x00)) ret = true;
    return ret;
}
