#define CaryatidReco_cxx

#include "CaryatidReco.h"

using namespace std;

CVSID("$Id: CaryatidReco.cxx,v 1.5 2007/11/11 08:48:46 rhatcher Exp $");
JOBMODULE(CaryatidReco,"CaryatidReco","");

//......................................................................

CaryatidReco::CaryatidReco() {

 fFile = 0;

 myPedAna = 0;
 
 fCaryatidTree = 0;
 fPedTree      = 0;
 fSparTree     = 0;

 //fGetTableTree = true;
 //fStoreTree    = true;
 //fOnline       = false;

 fGotCalledPed  = false;
 fGotCalledSpar = false;
}

//......................................................................

CaryatidReco::~CaryatidReco() {

  return;
}

//......................................................................

JobCResult CaryatidReco::Ana(const MomNavigator *mom) {

  if(!fFile) {
    RawRecord *rr = dynamic_cast<RawRecord *>(mom->GetFragment("RawRecord"));
    if (rr == 0) return JobCResult::kFailed;
      
    const RawDaqHeader* daqHdr = dynamic_cast<const RawDaqHeader*>(rr->GetRawHeader());      

    if (daqHdr) frunNum = daqHdr->GetRun();

    sprintf(gFileName,"CaryatidTree_%d.root",frunNum);


    if(fStoreTree) fFile = new TFile(gFileName,"RECREATE");

    if(fFile!=0) {
      fCaryatidTree = new TTree("CaryatidTree","Caryatid TTree");
      
      fCaryatidTree->Branch("run",  &frunNum,  "run/I");
      fCaryatidTree->Branch("error",&ferror,   "error/I");
      fCaryatidTree->Branch("crate",&fcrate,   "crate/I");
      fCaryatidTree->Branch("varc", &fvarc,    "varc/I");
      fCaryatidTree->Branch("vmm",  &fvmm,     "vmm/I");
      fCaryatidTree->Branch("vfb",  &fvfb,     "vfb/I");
      fCaryatidTree->Branch("va",   &fva,      "va/I");
      fCaryatidTree->Branch("vach", &fvach,    "vach/I");
      fCaryatidTree->Branch("adc",  &fadc,     "adc/I");
      fCaryatidTree->Branch("tdc",  &ftdc,     "tdc/D");
      fCaryatidTree->Branch("plane",&fplane,   "plane/I");
      fCaryatidTree->Branch("tUTC", &ftimeUTC, "tUTC/D");
    }
  }      
  if(fGetTableTree) {
      
    fPedTree = new TTree("pedTableTree","Online Pedestals Table TTree");
    fPedTree->Branch("crate", &icrate,  "crate/I");
    fPedTree->Branch("varc", &ivarc,      "varc/I");
    fPedTree->Branch("vmm",  &ivmm,       "vmm/I");
    fPedTree->Branch("vfb",  &ivfb,       "vfb/I");
    fPedTree->Branch("va",   &iva,        "va/I");
    fPedTree->Branch("vach", &ivach,      "vach/I");
    fPedTree->Branch("adc",  &fPedTable,  "adc/I");
    fPedTree->Branch("time", &fLoadTime,  "time/D");
    
    fSparTree = new TTree("sparTableTree","Sparsification Table TTree");
    fSparTree->Branch("crate", &icrate,"crate/I");
    fSparTree->Branch("varc", &ivarc,     "varc/I");
    fSparTree->Branch("vmm",  &ivmm,      "vmm/I");
    fSparTree->Branch("vfb",  &ivfb,      "vfb/I");
    fSparTree->Branch("va",   &iva,       "va/I");
    fSparTree->Branch("vach", &ivach,     "vach/I");
    fSparTree->Branch("adc",  &fSparTable,"adc/I");
    fSparTree->Branch("time", &fLoadTime, "time/D");
  }
  
  

  TObject* tobj;
  TIter    fragiter = mom->FragmentIter();

  while( ( tobj = fragiter.Next() ) ) { //Loop over MOM fragments
    RawRecord* rawrec;
    if( ( rawrec = dynamic_cast<RawRecord*>(tobj) ) ) {  //Loop over RawRecords

      //RAWSNARLHEARDERBLOCK info:
      const RawSnarlHeaderBlock* snarlHdr = 
	dynamic_cast<const RawSnarlHeaderBlock*> (rawrec->FindRawBlock("RawSnarlHeaderBlock"));
      if (snarlHdr) {
	ftimeUTC = snarlHdr->GetTriggerTime().GetSec(); //From 1/1/1970
	MSG("CaryatidReco", Msg::kInfo) << "Timeframe: " << snarlHdr->GetTimeFrameNum() << endl;
      }
      else MSG("CaryatidReco", Msg::kDebug) << "There was not RawSnarlHeaderBlock this time!" << endl;
      
      //Loop over other blocks:
      TIter rdbit = rawrec->GetRawBlockIter();
      TObject *tob;
      while ((tob = rdbit())) {

	//Pedestal Table read in:
	RawPedestalTableBlock* rptb;
	if( tob->InheritsFrom("RawPedestalTableBlock") ) {
	  rptb = dynamic_cast<RawPedestalTableBlock*>(tob);
          const RawCrateStatus *rcsped=rptb->GetCrateStatus();
          Int_t tempped= rcsped->GetCrate();
 	  this->GetPedestalTable(rptb, tempped);
	}
	
	//Sparsifier Table read in:
	RawSparsifierTableBlock* rstb;
	if( tob->InheritsFrom("RawSparsifierTableBlock") ) {
	  rstb = dynamic_cast<RawSparsifierTableBlock*>(tob);
          const RawCrateStatus *rcsspar=rstb->GetCrateStatus();
          Int_t tempspar= rcsspar->GetCrate();
	  this->GetSparsificationTable(rstb, tempspar);

	}

	//RawDigits get into Caryatid TTree:
	RawDigitDataBlock* rdb;
	if( tob->InheritsFrom("RawDigitDataBlock") ) {
	  rdb = dynamic_cast<RawDigitDataBlock*>(tob);
	  this->GetCaryatids(rdb);
	}
	//return JobCResult::kFailed; 
      }
    }
  }

  return JobCResult::kPassed;
}

//......................................................................

void CaryatidReco::GetPedestalTable(RawPedestalTableBlock *rptb, Int_t icrateped) {
  
//  if(!fGetTableTree || fGotCalledPed) return;
    if(!fGetTableTree) return;

  MSG("CaryatidReco", Msg::kDebug) << endl << "Creating the Pedestal TTree" << endl << endl;
  
  //  fGotCalledPed = true;

  //Load time of the table:
  fLoadTime = rptb->GetLoadTime().GetSec();
  
  MSG("CaryatidReco", Msg::kDebug) << "Pedestal Table Loaded on: " << endl;
  
  icrate=icrateped;
  
  for(ivarc = 0; ivarc < 3; ivarc++) {
      for(ivmm = 0; ivmm < 6; ivmm++) {
          for(ivfb = 0; ivfb < 2; ivfb++) {
              for(iva = 0; iva < 3; iva++) {
                  for(ivach = 0; ivach < 22; ivach++) {
                      
                      const RawChannelId thisRawChannel(Detector::kFar,
                                                        ElecType::kVA,
                                                        icrate, 
                                                        ivarc, 
                                                        ivmm, 
                                                        ivfb, 
                                                        iva, 
                                                        ivach);
                      
                      fPedTable = rptb->GetPedValue(thisRawChannel);
                      
                      MSG("CaryatidReco", Msg::kDebug) << fPedTable << "\t" 
					      << icrate    << "\t" 
					      << ivarc    << "\t" 
					      << ivmm     << "\t" 
					      << ivfb     << "\t" 
					      << iva      << "\t" 
					      << ivach    << endl;
  	      fPedTree->Fill();
	    }
	  }
	}
      }
    }

  return;
}

//......................................................................

void CaryatidReco::GetSparsificationTable(RawSparsifierTableBlock *rstb, Int_t icratespar) {

//  if(!fGetTableTree || fGotCalledSpar) return;
    if(!fGetTableTree) return;

  MSG("CaryatidReco", Msg::kDebug) << "Creating the Sparsification TTree" << endl << endl;
  
  
  //  fGotCalledSpar = true;
  
  //Load time of the table:	      
  fLoadTime = rstb->GetLoadTime().GetSec();
  
  MSG("CaryatidReco", Msg::kDebug) << "Sparsification Table Loaded on: " << endl; 
    
  icrate=icratespar;
  
  for(ivarc = 0; ivarc < 3; ivarc++) { 
      for(ivmm = 0; ivmm < 6; ivmm++) { 
          for(ivfb = 0; ivfb < 2; ivfb++) {
              for(iva = 0; iva < 3; iva++) {
                  for(ivach = 0; ivach < 22; ivach++) {
                
                      RawChannelId thisRawChannel(Detector::kFar,
                                                  ElecType::kVA,
                                                  icrate, 
                                                  ivarc, 
                                                  ivmm, 
                                                  ivfb, 
                                                  iva, 
                                                  ivach);
	      
	      fSparTable = rstb->GetThresholdValue(thisRawChannel);
	      			
	      MSG("CaryatidReco", Msg::kDebug) << fSparTable << "\t" 
					      << icrate    << "\t" 
					      << ivarc    << "\t" 
					      << ivmm     << "\t" 
					      << ivfb     << "\t" 
					      << iva      << "\t" 
					      << ivach    << endl;

//              cout << "Table in Crate2: " << icratespar << endl;
	      fSparTree->Fill();
	    }
	  }
	}
      }
    }

  return;
}

//......................................................................

void CaryatidReco::GetCaryatids(RawDigitDataBlock *rdb) {

  MSG("CaryatidReco", Msg::kDebug) << "Filling the Caryatid TTree with RawDigits data" << endl;

  TIter rdit = rdb->GetDatumIter();
  RawDigit *rd;
  
  //Get validity context
  while ( (rd = (RawDigit*) rdit()) ) {
    RawChannelId rawid = rd->GetChannel();
    
    fcrate = rawid.GetCrate();
    fvarc  = rawid.GetVarcId();
    fvmm   = rawid.GetVmm();
    fvfb   = rawid.GetVaAdcSel();
    fva    = rawid.GetVaChip();
    fvach  = rawid.GetVaChannel();
    
    fadc   = rd->GetADC();
    ftdc   = rd->GetTDC()*1.5625e-9;
    ferror = rd->GetErrorCode();
    
    if(!fOnline) {
      PlexHandle ph(rdb->GetVldContext());
      fplane = ph.GetSEIdAltL(rawid).GetPlane();
    }
    else fplane = -1;

    //
    //Fill Caryatid TTree:
    //
    if(fStoreTree) fCaryatidTree->Fill();

    //
    // Perform Online calculations
    //
    if(fOnline){ //&& ferror&2==2) {

      if(!myPedAna) myPedAna = CaryatidAna::InstantiateMe();

      Int_t key = Caryatid::EncriptMeAKey(fcrate,fvarc,fvmm,fvfb,fva,fvach);
      
      //If it does not found (i.e. iter points to end) -> then create it:
      if( myPedAna->mySP.find(key) == myPedAna->mySP.end() ) myPedAna->mySP[key] = new Caryatid();

      myPedAna->frun = frunNum;      
      myPedAna->mySP[key]->AddressMe(fcrate,fvarc,fvmm,fvfb,fva,fvach);
      myPedAna->mySP[key]->SetPlane(fplane);
      myPedAna->mySP[key]->SetError(ferror);
      myPedAna->mySP[key]->InputSPEntry(fadc);

      if(ferror>2)
	MSG("CaryatidReco", Msg::kError) << "Found ErrorCode (!=2): " << ferror << endl;

    }
    //if(ferror>2)
    //MSG("CaryatidReco", Msg::kError) << "Found Errors on data: " << ferror << endl;
  }
  return;
}

//......................................................................

void CaryatidReco::Config(const Registry& r) {

  Int_t tmpi;

  if(r.Get("GetPed-SparsTables", tmpi)) fGetTableTree  = tmpi;
  if(r.Get("StoreTree", tmpi))          fStoreTree     = tmpi;
  if(r.Get("OnlineVersion", tmpi))      fOnline        = tmpi;

  return;
}

//......................................................................

const Registry& CaryatidReco::DefaultConfig() const { 

  static Registry r;

  string name=this->JobCModule::GetName();
  name+=".config.default";
  r.SetName(name.c_str());

  r.UnLockValues();
  r.Set("GetPed-SparsTables",1);
  r.Set("StoreTree",1);
  r.Set("OnlineVersion",0);
  r.LockValues();

  return r;
}       


//......................................................................

void CaryatidReco::EndJob() {

  //
  // Store Tree into File
  //
  if(fStoreTree) {

    fFile->Write();
    fFile->Close();
  }

  //
  // Perform Quick Analysis for Online purposes:
  //
  if(fOnline && myPedAna) myPedAna->DoOnlineAnalysis(gFileName);

  return; 
}

//EOF
