/** @file
 * $Source: /home/cvsmanager/yoda/techmodel/RunTrailerReader.cpp,v $
 * $Id: RunTrailerReader.cpp,v 3.0 2005/03/04 15:54:11 kusanagi Exp $
 * $Author: kusanagi $
 * 
 * Implementation of the RunHeader class.
*/


#define UINT unsigned int
#define BYTE  unsigned char
#include <string>
#include <log4cxx/logger.h>
extern "C" {
#include <sys/time.h>
#include "CRC.h"
}

#include <fstream>
#include "stdio.h"
#include "ReaderAlgorithms.h"

#include "event/RunTrailerEvent.h"

using namespace pamela;
using namespace pamela::techmodel;

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

/**
 * Constructor. 
 */
RunTrailerReader::RunTrailerReader(void): 
  TechmodelAlgorithm(PacketType::Log, "TechmodelRunTrailerReader") { 
  logger->debug(_T("Constructor"));
  RunTrailer = new RunTrailerEvent();
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string RunTrailerReader::GetVersionInfo(void) const {
  return 
    "$Header: /home/cvsmanager/yoda/techmodel/RunTrailerReader.cpp,v 3.0 2005/03/04 15:54:11 kusanagi Exp $\n";
}

/**
 * Initialize the algorithm with a special run. This will initialize the
 * event reader routines for all packet types.
 */
void RunTrailerReader::Init(PamelaRun *run) {
  SetInputStream(run);
  run->WriteSubPacket(this, &RunTrailer, RunTrailer->Class());
  logger->debug(_T("Initialize"));
}

/**
 * Unpack the RunTrailer event from an input file.
 */
void RunTrailerReader::RunEvent(int EventNumber, long int length) throw (WrongCRCException){
    char     *subData;
    char      eventCRC[2];
    UINT16    subCRC;      //CRC of the data
    UINT16    readCRC;     //CRC read from the end of the subpacket
    long int  dataLength;
 
    //the 2 bytes subtracted belong to the final event CRC bytes
    dataLength = length - (long int)2;

    subData = new char[dataLength];
    InputFile->read(subData, sizeof(unsigned char)*dataLength);
    subCRC = CM_Compute_CRC16(0, (BYTE*)subData, dataLength);

    //took the final CRC to compare it with the previous calculated CRC of the data
    InputFile->read(eventCRC, sizeof(eventCRC));
    readCRC = (((UINT16)(eventCRC[0]<<8))&0xFF00) + (((UINT16)eventCRC[1])&0x00FF);
    
    if (subCRC != readCRC) throw WrongCRCException(" Wrong CRC for RunTrailer Packet ");

    RunTrailer->PKT_COUNTER         = (((UINT32)subData[0]<<24)&0xFF000000) + (((UINT32)subData[1]<<16)&0x00FF0000) +  (((UINT32)subData[2]<<8)&0x0000FF00) + (((UINT32)subData[3])&0x000000FF);
    RunTrailer->PKT_ReadyCounter    = (((UINT32)subData[4]<<24)&0xFF000000) + (((UINT32)subData[5]<<16)&0x00FF0000) +  (((UINT32)subData[6]<<8)&0x0000FF00) + (((UINT32)subData[7])&0x000000FF);
    RunTrailer->OBT_TYME_SYNC       = (((UINT32)subData[8]<<24)&0xFF000000) + (((UINT32)subData[9]<<16)&0x00FF0000) +  (((UINT32)subData[10]<<8)&0x0000FF00) + (((UINT32)subData[11])&0x000000FF);
    RunTrailer->LAST_TYME_SYNC_INFO = (((UINT32)subData[12]<<24)&0xFF000000) + (((UINT32)subData[13]<<16)&0x00FF0000) +  (((UINT32)subData[14]<<8)&0x0000FF00) + (((UINT32)subData[15])&0x000000FF);
    
}

