/*
 * LiveTimeCollection.cpp
 *
 *  Created on: 30-marth-2010
 *      Author: Vitaly Malakhov
 */

/*! @file LiveTimeCollection.cpp The LiveTimeCollection class implementation file */

#include "LiveTimeCollection.h"

void LiveTimeCollection::AddAction(CollectionAction *action) {
   _actions.push_back(action);
   _actionsPositions.push_back(GetSize() - 1);
   _sumLT.push_back(0);
   _sum.push_back(0);
}

void LiveTimeCollection::OnBad(PamLevel2 *event, int actNumber, unsigned int inc) {
   if((event->GetOrbitalInfo()->absTime - _currenttime > 1000.) || (_currenttime == 0)){
     for(unsigned int j = 0; j < _sumLT.size(); j++ ) _sumLT[j] = 0;
   } 
   _currenttime = event->GetOrbitalInfo()->absTime;
   unsigned int Inc = 0;
   if(inc == 0) Inc = event->GetTrigLevel2()->dltime[0]; else Inc = inc;
   for(unsigned int j = actNumber; j <= _actions.size()-1; j++) _sumLT[j] += Inc;
}

Float_t LiveTimeCollection::GetSumLiveTime(unsigned int actNumber) {
   if(actNumber >= _sum.size()) return -1; 
    return _sum[actNumber] * 0.16 /1000. ;
}

int LiveTimeCollection::ApplyCut(PamLevel2 *event) {

  _nEv++;

  // Execute the actions placed before the cuts
  unsigned int iBeforeCuts = 0;
  if (_actions.size() > 0) {
    while (_actionsPositions[iBeforeCuts] == -1) {
      _actions[iBeforeCuts]->OnGood(event);
      iBeforeCuts++;
      if (iBeforeCuts == _actions.size())
        break;
    }
  }

  // Apply the cuts
  if (_cuts.size() == 0) {
    _nGood++;
    OnGood(event);
    return CUTOK;
  }

  unsigned int firstFailed = _cuts.size();
  for (unsigned int iCut = 0; iCut < _cuts.size(); iCut++) {
    if (_cuts[iCut]->ApplyCut(event) != CUTOK && firstFailed == _cuts.size()) {
      firstFailed = iCut;
      break;
    }
  }

  Int_t actNumber = 0;
  unsigned int Inc = 0;

  //Do actions
  if (_actions.size() > 0) {
    Bool_t che = true;
    Int_t inc = 0;
    unsigned int lastPosition = _cuts.size();
    for (unsigned int i = iBeforeCuts; i < _actions.size(); i++) {
	actNumber = i-1;
      if (_actionsPositions[i] < (int) firstFailed){
	 if((event->GetOrbitalInfo()->absTime - _currenttime > 1000.) || (_currenttime == 0)){
     	   for(unsigned int j = 0; j < _sumLT.size(); j++ ) _sumLT[j] = 0;
   	 }
	 if( che ){
	   inc = event->GetTrigLevel2()->dltime[0];
	   Inc = inc;
	   _sum[i] += _sumLT[i]+inc;
	   event->GetTrigLevel2()->dltime[0] += _sumLT[i] ;
	   che = false;
	 }else _sum[i] += (_sumLT[i]+inc);
        _actions[i]->OnGood(event);
	 _sumLT[i] = 0;
	 _currenttime = event->GetOrbitalInfo()->absTime;
	}
      else { // A cut has failed
        if (lastPosition == _cuts.size()) // Record the position of the end of the bunch
          lastPosition = _actionsPositions[i];
        if (_actionsPositions[i] > (int) lastPosition) // Don't do actions at the end of successive bunches
          break;
        _actions[i]->OnBad(event, i);
      }
    }
  }

  if (firstFailed == _cuts.size()) {
    _nGood++;
    OnGood(event);
    return CUTOK;
  }
  else {
    OnBad(event, actNumber, Inc);
    return firstFailed;
  }
}

void LiveTimeCollection::Finalize() {
  ofstream livetimereport;
  livetimereport.open (_livetimereport);
  livetimereport << "Action name\t\tsum live time"<<endl;
  for (UInt_t i = 0; i < _sum.size(); i++) livetimereport << _actions[i]->GetName()<<"\t"<<GetSumLiveTime(i)<<"sec"<<endl;
  livetimereport.close();
}
