/** @file
 * $Source: /home/cvsmanager/yoda/event/EventCounter.cpp,v $
 * $Id: EventCounter.cpp,v 3.0 2005/03/04 15:54:11 kusanagi Exp $
 * $Author: kusanagi $
 * 
 * Implementation of the EventCounter class.
 */
#include <log4cxx/logger.h>
#include <sstream>

#include "EventCounter.h"
#include "PscuHeader.h"


static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("pamela.techmodel.EventCounter"));
static std::stringstream oss;
using namespace pamela;

/**
 * Create a new event counter for a certain run.
 * @param run Run number.
 */
EventCounter::EventCounter(int run):
  // New Packets.
  Pscu(0),
  PhysEndRun(0),
  CalibCalPulse1(0),
  CalibCalPulse2(0),
  Physics(0),
  CalibTrkBoth(0),
  CalibTrk1(0),
  CalibTrk2(0),
  CalibTrd(0),
  CalibTof(0),
  CalibS4(0),
  CalibCalPed(0),
  Calib1_Ac1(0),
  Calib1_Ac2(0),
  Calib2_Ac1(0),
  Calib2_Ac2(0),
  RunHeader(0),
  RunTrailer(0),
  CalibHeader(0),
  CalibTrailer(0),
  InitHeader(0),
  InitTrailer(0),
  EventTrk(0),
  TestTrk(0),
  TestTof(0),
  Log(0),
  VarDump(0),
  ArrDump(0),
  TabDump(0),
  Tmtc(0),
  Mcmd(0),
  ForcedFECmd(0),
  Ac1Init(0),
  CalInit(0),
  TrkInit(0),
  TofInit(0),
  TrgInit(0),
  NdInit(0),
  S4Init(0),
  Ac2Init(0),
  CalAlarm(0),
  AcAlarm(0),
  TrkAlarm(0),
  TrgAlarm(0),
  TofAlarm(0),
  S4Alarm(0),
  TsbT(0),
  TsbB(0),
  RunNumber(run) { 
    CMap.insert(CounterMap::value_type(PacketType::Pscu,            &Pscu));
    CMap.insert(CounterMap::value_type(PacketType::PhysEndRun,      &PhysEndRun));
    CMap.insert(CounterMap::value_type(PacketType::CalibCalPulse1,  &CalibCalPulse1));
    CMap.insert(CounterMap::value_type(PacketType::CalibCalPulse2,  &CalibCalPulse2));
    CMap.insert(CounterMap::value_type(PacketType::Physics,         &Physics));
    CMap.insert(CounterMap::value_type(PacketType::CalibTrkBoth,    &CalibTrkBoth));
    CMap.insert(CounterMap::value_type(PacketType::CalibTrk1,       &CalibTrk1));
    CMap.insert(CounterMap::value_type(PacketType::CalibTrk2,       &CalibTrk2));
    CMap.insert(CounterMap::value_type(PacketType::CalibTrd,        &CalibTrd));
    CMap.insert(CounterMap::value_type(PacketType::CalibTof,        &CalibTof));
    CMap.insert(CounterMap::value_type(PacketType::CalibS4,         &CalibS4));
    CMap.insert(CounterMap::value_type(PacketType::CalibCalPed,     &CalibCalPed));
    CMap.insert(CounterMap::value_type(PacketType::Calib1_Ac1,      &Calib1_Ac1));
    CMap.insert(CounterMap::value_type(PacketType::Calib1_Ac2,      &Calib1_Ac2));
    CMap.insert(CounterMap::value_type(PacketType::Calib2_Ac1,      &Calib2_Ac1));
    CMap.insert(CounterMap::value_type(PacketType::Calib2_Ac2,      &Calib2_Ac2));
    CMap.insert(CounterMap::value_type(PacketType::RunHeader,       &RunHeader));
    CMap.insert(CounterMap::value_type(PacketType::RunTrailer,      &RunTrailer));
    CMap.insert(CounterMap::value_type(PacketType::CalibHeader,     &CalibHeader));
    CMap.insert(CounterMap::value_type(PacketType::CalibTrailer,    &CalibTrailer));  
    CMap.insert(CounterMap::value_type(PacketType::InitHeader,      &InitHeader));
    CMap.insert(CounterMap::value_type(PacketType::InitTrailer,     &InitTrailer));  
    CMap.insert(CounterMap::value_type(PacketType::EventTrk,        &EventTrk));  
    CMap.insert(CounterMap::value_type(PacketType::TestTrk,         &TestTrk));  
    CMap.insert(CounterMap::value_type(PacketType::TestTof,         &TestTof));  
    CMap.insert(CounterMap::value_type(PacketType::Log,             &Log));
    CMap.insert(CounterMap::value_type(PacketType::VarDump,         &VarDump));
    CMap.insert(CounterMap::value_type(PacketType::ArrDump,         &ArrDump));
    CMap.insert(CounterMap::value_type(PacketType::TabDump,         &TabDump));
    CMap.insert(CounterMap::value_type(PacketType::Tmtc,            &Tmtc));
    CMap.insert(CounterMap::value_type(PacketType::Mcmd,            &Mcmd));
    CMap.insert(CounterMap::value_type(PacketType::ForcedFECmd,     &ForcedFECmd));
    CMap.insert(CounterMap::value_type(PacketType::Ac1Init,         &Ac1Init));
    CMap.insert(CounterMap::value_type(PacketType::CalInit,         &CalInit));
    CMap.insert(CounterMap::value_type(PacketType::TrkInit,         &TrkInit));
    CMap.insert(CounterMap::value_type(PacketType::TofInit,         &TofInit));
    CMap.insert(CounterMap::value_type(PacketType::NdInit,          &NdInit));
    CMap.insert(CounterMap::value_type(PacketType::S4Init,          &S4Init));
    CMap.insert(CounterMap::value_type(PacketType::Ac2Init,         &Ac2Init));
    CMap.insert(CounterMap::value_type(PacketType::CalAlarm,        &CalAlarm));
    CMap.insert(CounterMap::value_type(PacketType::AcAlarm,         &AcAlarm));
    CMap.insert(CounterMap::value_type(PacketType::TrkAlarm,        &TrkAlarm));
    CMap.insert(CounterMap::value_type(PacketType::TrgAlarm,        &TrgAlarm));
    CMap.insert(CounterMap::value_type(PacketType::TofAlarm,        &TofAlarm));
    CMap.insert(CounterMap::value_type(PacketType::S4Alarm,         &S4Alarm));
    CMap.insert(CounterMap::value_type(PacketType::TsbT,            &TsbT));
    CMap.insert(CounterMap::value_type(PacketType::TsbB,            &TsbB));
}

/**
 * Increment the event counter for a certain packet.
 * @param type Event type to be incremented.
 */
void EventCounter::Increment(PacketType const * type) throw (NotExistingCounterException){
  CounterMap::iterator p = CMap.find(type);
  if (p != CMap.end()) {
    int *counter = p->second;
    (*counter)++;
    oss.str("");
    oss << " Counter." <<  type->GetName() << " = " <<  (*counter);
    logger->info(oss.str().c_str());
  } else {
    oss.str("");
    oss << "\n No counter of type  " << type->GetName().c_str();
    throw NotExistingCounterException(oss.str().c_str());
  }
}

/**
 * Get the counter corresponding to a certain packet type.
 * @param type Event type to be incremented.
 * @return The counter of that packet type. For the current event type, 
 * this is the actual event number. For all other types, this is the event 
 * number of the last read event of that type.
 * @retval -1 if there was no event of this type.
 */
int EventCounter::Get(PacketType const * type) const throw (NotExistingCounterException){
  const CounterMap::const_iterator p = CMap.find(type);
  if (p != CMap.end()) {
    const int *counter = p->second;
    return *counter;
  } else {
    throw NotExistingCounterException(type->GetName().c_str());
    return -1;
  }
}

/**
 * Get the counter of the next event corresponding to a certain packet type.
 * @param type Event type to be incremented.
 * @return The next counter of that packet type. 
 * @retval -1 if there was no event of this type.
 */
int EventCounter::Next(PacketType const * type) const throw (NotExistingCounterException){
  const CounterMap::const_iterator p = CMap.find(type);
  if (p != CMap.end()) {
    const int *counter = p->second;
    return *counter + 1;
  } else {
    throw NotExistingCounterException(type->GetName().c_str());
    return -1;
  }
}

/**
 * Get the all the counters 
  * @retval 0 if there was no event of this type.
 */
void EventCounter::PrintCounters() const {
  for(CounterMap::const_iterator p = CMap.begin(); p != CMap.end(); p++) {
  oss.str("");
  oss <<  " Counter." <<  (p->first)->GetName()  <<   " \t \t " <<  (*p->second);
  logger->info(oss.str().c_str());
  } 
}
