#include "DQHotColdElectronics.h"
#include "RawChip.h"

#include "MessageService/MsgService.h"

//
// $Log $
//

ClassImp(DQHotColdElectronics)
                       
CVSID("$Id: DQHotColdElectronics.cxx,v 1.1 2006/03/19 17:24:34 blake Exp $");

DQHotColdElectronics::DQHotColdElectronics() :
  fTime(-1), 
  fSource(-1), 
  fNumberOfCrates(-1),
  fNumberOfCratesInReadout(-1),
  fFrameTime(0.0),
  fRawReadout(0),
  fHotColdElectronicsList(0)
{
  for(Int_t k=0; k<2; k++){
    fColdChipMask[k]=0; fHotChipMask[k]=0;
  }

  fRawReadout = new RawReadout();

  fHotColdElectronicsList = new TObjArray();
}
 
DQHotColdElectronics::DQHotColdElectronics(const DQHotColdElectronics& rhs) :
  TObject(rhs),
  fTime(rhs.fTime), 
  fSource(rhs.fSource), 
  fNumberOfCrates(rhs.fNumberOfCrates),
  fNumberOfCratesInReadout(rhs.fNumberOfCratesInReadout),
  fFrameTime(rhs.fFrameTime),
  fRawReadout(rhs.fRawReadout), 
  fHotColdElectronicsList(rhs.fHotColdElectronicsList)
{
  for(Int_t k=0; k<2; k++){
    fColdChipMask[k]=rhs.fColdChipMask[k];
    fHotChipMask[k]=rhs.fHotChipMask[k];
  }
}
   
DQHotColdElectronics::~DQHotColdElectronics()
{
  delete fRawReadout;

  fHotColdElectronicsList->Delete();
  delete fHotColdElectronicsList;
}

void DQHotColdElectronics::Process(RawTpSinglesSummaryBlock* rdb)
{
  MSG("DataQuality",Msg::kVerbose) << " DQHotColdElectronics::Process(RawTpSinglesSummaryBlock) " << endl;

  // Min/Max Singles Rates
  // =====================
  // Far Detector: normal rates are [50,5000] Hz
  // Near Detector: normal rates are [0,100000] Hz

  Int_t fMinVaRate=50;
  Int_t fMaxVaRate=5000;
  Int_t fMinQieRate=0;
  Int_t fMaxQieRate=100000;

  // TpSinglesSummaryBlock Source
  // ============================
  // Extract the TP singles measurement parameters
  // [time stamp, frame time (end-start), number of crates (ROP mask)]

  fTime=rdb->GetStartTimeStamp().GetSec();
  fFrameTime=(rdb->GetEndTimeStamp().GetSec()-rdb->GetStartTimeStamp().GetSec())+1.0e-9*(rdb->GetEndTimeStamp().GetNanoSec()-rdb->GetStartTimeStamp().GetNanoSec());
  fNumberOfCrates=rdb->GetNumberOfCrates();
  fNumberOfCratesInReadout=0;

  for(Int_t k=0;k<fNumberOfCrates;k++){
    if( rdb->GetHitsPerSecByCrate(k)>0 ) fNumberOfCratesInReadout++;
  }

  MSG("DataQuality",Msg::kVerbose) << "   Time=" << fTime << endl;
  MSG("DataQuality",Msg::kVerbose) << "   FrameTime=" << fFrameTime << endl;
  MSG("DataQuality",Msg::kVerbose) << "   NumberOfCrates=" << fNumberOfCrates << endl;
  MSG("DataQuality",Msg::kVerbose) << "   NumberOfCratesInReadout=" << fNumberOfCratesInReadout << endl;

  if( fFrameTime<=0 ){
    MSG("DataQuality",Msg::kWarning) << "     WARNING: TP summary frame time is corrupted " << endl;
  }

  // TpSinglesSummaryBlock Source
  // ============================
  // Extract the detector/electronics type and the granularity 
  // at which the rates have been recorded - only rates at the
  // VA chip and QIE menu level can be handled currently.

  fSource=rdb->GetSource();
  MSG("DataQuality",Msg::kVerbose) << "   Source=" << fSource << endl;

  Detector::Detector_t fDetector(Detector::kUnknown);

  switch( fSource ){
    case 0: // Crate only   
      fDetector = Detector::kUnknown;   
      break;
    case 1: // Crate and VARC (VA)  
      fDetector = Detector::kFar;
      break;
    case 2: // Crate and VFB/ADCSEL (VA)  
      fDetector = Detector::kFar;
      break;
    case 3: // Crate and VACHIP (VA)
      fDetector = Detector::kFar;  
      break;
    case 4: // Crate and Plane 
      fDetector = Detector::kUnknown;            
      break;
    case 5: // Crate and MASTER (QIE)
      fDetector = Detector::kNear;        
      break;
    case 6: // Crate and MINDER (QIE) 
      fDetector = Detector::kNear;
      break;
    case 7: // Crate and MENU (QIE)  
      fDetector = Detector::kNear;  
      break;
    default:                 
      break;
  }

  // Reset the hot/cold chip masks
  for(Int_t k=0;k<2;k++){
    fColdChipMask[k]=0; fHotChipMask[k]=0;
  }

  // Reset the lists of hot/cold chips
  fHotColdElectronicsList->Delete();

  // Iterate over raw channels and record any hot/cold chips
  typedef std::map<RawChannelId,UInt_t> RCIdToRateMap;
  const RCIdToRateMap& rates = rdb->GetRates();
  RCIdToRateMap::const_iterator rateItr = rates.begin();
  RCIdToRateMap::const_iterator rateEnd = rates.end();
  while ( rateItr != rateEnd ) {
    RawChannelId rawch = rateItr->first;
    Int_t rawrate = rateItr->second;
    Int_t correctedrate = (Int_t)(rawrate/fFrameTime);
    Int_t rate = correctedrate;
    Int_t crate = rawch.GetCrate();

    RawReadout::ReadoutType_t readout = fRawReadout->GetReadoutType(rawch);

    // Near Detector, QIE Electronics (Source 7 - QIE Menus)
    if( fSource==7
     && fDetector==Detector::kNear && rawch.GetElecType()==ElecType::kQIE ){

      if( readout==RawReadout::kDetector && rate<fMinQieRate){
        RawChip* chip = new RawChip(rawch,0,0,readout,RawChip::kCold,rate);
        fHotColdElectronicsList->Add(chip);
        if( crate>=0 && crate<8 ) fColdChipMask[0]++;
      }

      if( readout==RawReadout::kDetector && rate>fMaxQieRate){
        RawChip* chip = new RawChip(rawch,0,0,readout,RawChip::kHot,rate);
        fHotColdElectronicsList->Add(chip);
        if( crate>=0 && crate<8 ) fHotChipMask[0]++;
      }
    }
    
    // Far Detector, VA Electronics (Souce 3 - VA chips)
    // NB: there are currently no hot Veto Shield chips!
    if( fSource==3
     && fDetector==Detector::kFar && rawch.GetElecType()==ElecType::kVA ){

      if( readout==RawReadout::kDetector && rate<fMinVaRate ){
        RawChip* chip = new RawChip(rawch,0,0,readout,RawChip::kCold,rate);
        fHotColdElectronicsList->Add(chip);
        if( crate>=0 && crate<8 ) fColdChipMask[0]++;
        if( crate>=8 && crate<16 ) fColdChipMask[1]++;
      }

      if( readout==RawReadout::kDetector && rate>fMaxVaRate ){
        RawChip* chip = new RawChip(rawch,0,0,readout,RawChip::kHot,rate);
        fHotColdElectronicsList->Add(chip);
        if( crate>=0 && crate<8 ) fHotChipMask[0]++;
        if( crate>=8 && crate<16 ) fHotChipMask[1]++;
      }

      if( readout==RawReadout::kVetoShield && rate<fMinVaRate ){
        RawChip* chip = new RawChip(rawch,0,0,readout,RawChip::kCold,rate);
        fHotColdElectronicsList->Add(chip);
        if( crate>=0 && crate<8 ) fColdChipMask[0]++;
        if( crate>=8 && crate<16 ) fColdChipMask[1]++;
      }
    }

    rateItr++;
  }

  MSG("DataQuality",Msg::kVerbose) << " Found " << 1+this->GetLast() << " hot/cold chips [cold=" << fColdChipMask[0]+fColdChipMask[1] << ", hot=" << fHotChipMask[0]+fHotChipMask[1] << "]" << endl;

}

Int_t DQHotColdElectronics::GetTime() const
{
  return fTime;
}

Int_t DQHotColdElectronics::GetSource() const
{
  return fSource;
}

Int_t DQHotColdElectronics::GetNumberOfCrates() const
{
  return fNumberOfCrates;
}

Int_t DQHotColdElectronics::GetNumberOfCratesInReadout() const
{
  return fNumberOfCratesInReadout;
}

Int_t DQHotColdElectronics::GetColdChips(Int_t sm) const
{
  if( sm==0 ) return fColdChipMask[0]+fColdChipMask[1];
  if( sm==1 ) return fColdChipMask[0];
  if( sm==2 ) return fColdChipMask[1];
  return -1;
}
  
Int_t DQHotColdElectronics::GetHotChips(Int_t sm) const
{
  if( sm==0 ) return fHotChipMask[0]+fHotChipMask[1];
  if( sm==1 ) return fHotChipMask[0];
  if( sm==2 ) return fHotChipMask[1];
  return -1;
}

Int_t DQHotColdElectronics::GetLast() const
{
  return fHotColdElectronicsList->GetLast();
}
  
TObject* DQHotColdElectronics::At(Int_t i) const
{
  return (TObject*)(fHotColdElectronicsList->At(i));
}
