/** @file
 * $Source: /afs/ba.infn.it/user/pamela/src/CVS/chewbacca/event/EventCounter.cpp,v $
 * $Id: EventCounter.cpp,v 1.4 2009/08/04 13:58:16 mocchiut Exp $
 * $Author: mocchiut $
 * 
 * Implementation of the EventCounter class.
 */
////#include <log4cxx/logger.h>
#include <sstream>
#include <iostream>//mmmm

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

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

using namespace pamela;


mapval::mapval(): count(0), name(""){ }

mapval::mapval(TString n, Int_t *i): count(i), name(n){ }

mappa::mappa(){  
  val = 0;
  this->Clear();
}

void mappa::Clear(Option_t *t){
  //	cout << " mappa clear" << endl;
  t="";
  if ( val ){
    val->Delete();
    val = 0;
  };
  fend = false;
  entries = 0;
}

void mappa::Set(){
  //  cout << " in mappa set" << endl;
  if (val) delete val;
  val = new TClonesArray("pamela::mapval",47);
  //  cout << " out mappa set" << endl;
}

void mappa::Delete(Option_t *t){
  //  cout << " mappa del" << endl;
  if ( val ){
    val->Delete();
    val = 0;
    //		delete val;
  };
  delete this;
}

void mappa::Insert(TString nme, Int_t *valu){
  //  cout << " mappa insert " << nme.Data() << " valu " << *valu << endl;
  if ( !val ) this->Set();
  TClonesArray &t = *val;
  new(t[entries]) mapval(nme,valu);
  entries++;
}

mapval::mapval(const mapval &t){
  name = t.name;
  count = t.count;
}

mapval* mappa::Find(TString n){
  Bool_t fo = false;
  fend = false;
  mapval *c = NULL;
  for (Int_t i=0; i < entries; i++){
    c = (mapval*)val->At(i);
    if ( c && !strcmp(c->name.Data(),n.Data()) ){
      fo = true;
      break;
    };
  };
  if ( !fo ) fend = true;
  return c;
}

/**
 * Create a new event counter for a certain run.
 * @param run Run number.
 */
EventCounter::EventCounter(int run):
	// New Packets.
  RunNumber(run),
  Pscu(0),
  PhysEndRun(0),
  CalibCalPulse1(0),
  CalibCalPulse2(0),
  Physics(0),
  CalibTrkBoth(0),
  CalibTrk1(0),
  CalibTrk2(0),
  CalibCal(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),
  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),
  Ac1Alarm(0),
  TrkAlarm(0),
  TrgAlarm(0),
  TofAlarm(0),
  S4Alarm(0),
  Ac2Alarm(0),
  TsbT(0),
  TsbB(0) { 
    CMap.Set();
    CMap.Insert(PacketType::Physics->GetName(),         &Physics);
    CMap.Insert(PacketType::Pscu->GetName(),            &Pscu);
    CMap.Insert(PacketType::RunHeader->GetName(),       &RunHeader);
    CMap.Insert(PacketType::RunTrailer->GetName(),      &RunTrailer);
    CMap.Insert(PacketType::PhysEndRun->GetName(),      &PhysEndRun);
    CMap.Insert(PacketType::InitHeader->GetName(),      &InitHeader);
    CMap.Insert(PacketType::InitTrailer->GetName(),     &InitTrailer);  
    CMap.Insert(PacketType::Log->GetName(),             &Log);
    CMap.Insert(PacketType::VarDump->GetName(),         &VarDump);
    CMap.Insert(PacketType::ArrDump->GetName(),         &ArrDump);
    CMap.Insert(PacketType::TabDump->GetName(),         &TabDump);
    CMap.Insert(PacketType::Tmtc->GetName(),            &Tmtc);
    CMap.Insert(PacketType::Mcmd->GetName(),            &Mcmd);
    CMap.Insert(PacketType::TsbT->GetName(),            &TsbT);
    CMap.Insert(PacketType::TsbB->GetName(),            &TsbB);
    CMap.Insert(PacketType::CalibHeader->GetName(),     &CalibHeader);
    CMap.Insert(PacketType::CalibTrailer->GetName(),    &CalibTrailer);  
    CMap.Insert(PacketType::CalibCalPulse1->GetName(),  &CalibCalPulse1);
    CMap.Insert(PacketType::CalibCalPulse2->GetName(),  &CalibCalPulse2);
    CMap.Insert(PacketType::CalibTrkBoth->GetName(),    &CalibTrkBoth);
    CMap.Insert(PacketType::CalibTrk1->GetName(),       &CalibTrk1);
    CMap.Insert(PacketType::CalibTrk2->GetName(),       &CalibTrk2);
    CMap.Insert(PacketType::CalibS4->GetName(),         &CalibS4);
    CMap.Insert(PacketType::CalibCalPed->GetName(),     &CalibCalPed);
    CMap.Insert(PacketType::Calib1_Ac1->GetName(),      &Calib1_Ac1);
    CMap.Insert(PacketType::Calib2_Ac1->GetName(),      &Calib2_Ac1);
    CMap.Insert(PacketType::Calib1_Ac2->GetName(),      &Calib1_Ac2);
    CMap.Insert(PacketType::Calib2_Ac2->GetName(),      &Calib2_Ac2);
    CMap.Insert(PacketType::CalibCal->GetName(),        &CalibCal);
    CMap.Insert(PacketType::EventTrk->GetName(),        &EventTrk);  
    CMap.Insert(PacketType::Ac1Init->GetName(),         &Ac1Init);
    CMap.Insert(PacketType::CalInit->GetName(),         &CalInit);
    CMap.Insert(PacketType::TrkInit->GetName(),         &TrkInit);
    CMap.Insert(PacketType::TofInit->GetName(),         &TofInit);
    CMap.Insert(PacketType::TrgInit->GetName(),         &TrgInit);
    CMap.Insert(PacketType::NdInit->GetName(),          &NdInit);
    CMap.Insert(PacketType::S4Init->GetName(),          &S4Init);
    CMap.Insert(PacketType::Ac2Init->GetName(),         &Ac2Init);
    CMap.Insert(PacketType::CalAlarm->GetName(),        &CalAlarm);
    CMap.Insert(PacketType::Ac1Alarm->GetName(),        &Ac1Alarm);
    CMap.Insert(PacketType::TrkAlarm->GetName(),        &TrkAlarm);
    CMap.Insert(PacketType::TrgAlarm->GetName(),        &TrgAlarm);
    CMap.Insert(PacketType::TofAlarm->GetName(),        &TofAlarm);
    CMap.Insert(PacketType::S4Alarm->GetName(),         &S4Alarm);
    CMap.Insert(PacketType::Ac2Alarm->GetName(),        &Ac2Alarm);
    CMap.Insert(PacketType::ForcedFECmd->GetName(),     &ForcedFECmd);
    CMap.Insert(PacketType::CalibTof->GetName(),        &CalibTof);
  
}

/**
 * Increment the event counter for a certain packet.
 * @param type Event type to be incremented.
 */
void EventCounter::Increment(PacketType const * type) throw (NotExistingCounterException){
  //  cout << " increment "<< endl;
  mapval *p = CMap.Find(type->GetName());
  if ( !CMap.end()) {    
    //    cout << " A Counter." <<  type->GetName() << " = " <<  (*(&p->count)) << endl;
    (*(p->count))++; 
    //(*(&p->count))++; 
    //    cout << " B Counter." <<  type->GetName() << " = " <<  (*(&p->count)) << endl;
  } else {    
    oss.str("");
    oss << "\n No counter of type  " << type->GetName();
    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) throw (NotExistingCounterException){
  //  cout << " get "<< endl;
  mapval *p = CMap.Find(type->GetName());
  if ( !CMap.end()) { 
    //    cout << " C Counter." <<  type->GetName() << " = " <<  (*(p->count)) << endl;
    return ((*(p->count)));
    //    return ((*(&p->count)));
  } else {
    throw NotExistingCounterException(type->GetName());
    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) throw (NotExistingCounterException){
  //  cout << " next "<< endl;
  mapval *p = CMap.Find(type->GetName());
  if ( !CMap.end()) { 
    //    cout << " NEXT Counter." <<  type->GetName() << " = " <<  (*(p->count))+1 << endl;
    return ((*(p->count)) + 1);
    //    return ((*(&p->count)) + 1);
    //    return ((&(p->count)) + 1);
  } else {
    throw NotExistingCounterException(type->GetName());
    return -1;
  }
}

/**
 * Get the all the counters 
  * @retval 0 if there was no event of this type.
 */
void EventCounter::PrintCounters(){
  std::cout<<"PrintCounters:"<<std::endl;
  //
  for (Int_t i=0; i < CMap.GetEntries(); i++){
    mapval *p = CMap.Get(i);
    oss.str("");
    oss <<  " Counter." <<  (p->name).Data()  <<   " \t \t " <<  (*(p->count));
    //    oss <<  " Counter." <<  (p->name).Data()  <<   " \t \t " <<  (*(&p->count));
    //    oss <<  " Counter." <<  (p->name).Data()  <<   " \t \t " <<  (&(p->count));
    std::cout<<oss.str()<<std::endl;
  };
}

ClassImp(mapval)
ClassImp(mappa)
ClassImp(EventCounter)	
