/**
 * \file src/CaloLevel2.cpp
 * \author Emiliano Mocchiutti
 *
**/
#include <TObject.h>
#include <CaloLevel2.h>

//
ClassImp(CaloTrkVar);
ClassImp(CaloLevel2);

/**
 * CaloTrkVar constructor
**/
CaloTrkVar::CaloTrkVar() {
  this->Clear();
};

/**
 * Clear variables
**/
void CaloTrkVar::Clear() {
  trkseqno = 0;
  noint = 0;
  ncore = 0;
  qcore = 0.;
  ncyl = 0;
  qcyl = 0.;
  qtrack = 0.;
  qtrackx = 0.;
  qtracky = 0.;
  dxtrack = 0.;
  dytrack = 0.;
  qlast = 0.;
  nlast = 0;
  qpre = 0.;
  npre = 0;
  qpresh = 0.;
  npresh = 0;
  qtr = 0.;
  ntr = 0;
  planetot = 0;
  qmean = 0.;
  qlow = 0.;
  nlow = 0;
  dX0l = 0.;
  memset(tbar, 0, 2*22*sizeof(Float_t));
  memset(tibar, 0, 2*22*sizeof(Int_t));
}

/**
 * Copies from t to this
**/
CaloTrkVar::CaloTrkVar(const CaloTrkVar &t){
  trkseqno = t.trkseqno;
  noint = t.noint;
  ncore = t.ncore;
  qcore = t.qcore;
  ncyl = t.ncyl;
  qcyl = t.qcyl;
  qtrack = t.qtrack;
  qtrackx = t.qtrackx;
  qtracky = t.qtracky;
  dxtrack = t.dxtrack;
  dytrack = t.dytrack;
  qlast = t.qlast;
  nlast = t.nlast;
  qpre = t.qpre;
  npre = t.npre;
  qpresh = t.qpresh;
  npresh = t.npresh;
  qtr = t.qtr;
  ntr = t.ntr;  
  planetot = t.planetot;
  qmean = t.qmean;
  dX0l = t.dX0l;
  qlow = t.qlow;
  nlow = t.nlow;
  memcpy(tibar,t.tibar,sizeof(tibar));
  memcpy(tbar,t.tbar,sizeof(tbar));
}

/**
 * CaloLevel2 constructor
**/
CaloLevel2::CaloLevel2() {    
  //
//  CaloTrk = new TClonesArray("CaloTrkVar",1); //ELENA
  CaloTrk = 0; //ELENA
  //
  this->Clear();
  //
};
/**
 * Create the TClonesArray
**/
void CaloLevel2::Set(){//ELENA
    if(!CaloTrk)CaloTrk = new TClonesArray("CaloTrkVar",1); //ELENA
}//ELENA

/**
 * Clear the CaloLevel2 object
 **/
void CaloLevel2::Clear() {    
  //
//  CaloTrk->Clear(); //ELENA
  if(CaloTrk)CaloTrk->Delete(); //ELENA
  //
  nstrip = 0;
  qtot = 0.;
  //  impx = 0.;
  //  impy = 0.;
  qmax = 0.;
  nx22 = 0;
  qx22 = 0.;
  elen = 0.;
  selen = 0.;
  memset(perr, 0, 4*sizeof(Int_t));
  memset(swerr, 0, 4*sizeof(Int_t));
  memset(crc, 0, 4*sizeof(Int_t));
  memset(qq, 0, 4*sizeof(Int_t));
  memset(varcfit, 0, 4*sizeof(Float_t));
  memset(npcfit, 0, 4*sizeof(Int_t));
  memset(tanx, 0, 2*sizeof(Int_t));
  memset(tany, 0, 2*sizeof(Int_t));
  memset(fitmode, 0, 2*sizeof(Int_t));
  memset(planemax, 0, 2*sizeof(Int_t));
  memset(cibar, 0, 2*22*sizeof(Int_t));
  memset(cbar, 0, 2*22*sizeof(Float_t));
  good = 0;
  selftrigger = 0;
  //
};

/**
 * Delete the CaloLevel2 object
 **/
void CaloLevel2::Delete() {     //ELENA
  if(CaloTrk){ //ELENA
      CaloTrk->Delete(); //ELENA
      delete CaloTrk; //ELENA
  }     //ELENA
} //ELENA

/**
 * Fills a struct cCaloLevel2 with values from a CaloLevel2 object (to put data into a F77 common).
 */
void CaloLevel2::GetLevel2Struct(cCaloLevel2 *l2) const {
 
  l2->good = good;      
  l2->selftrigger = selftrigger;
  l2->nstrip = nstrip;     
  l2->nx22 = nx22;  
  l2->qtot = qtot;     
  l2->qx22 = qx22;     
  l2->qmax = qmax;     
  //  l2->impx = impx;     
  //  l2->impy = impy;     
  //  l2->tanx = tanx;     
  //  l2->tany = tany;  
  l2->elen = elen;      
  l2->selen = selen; 
        
  for(Int_t i=0;i<2;i++){
    l2->planemax[i] = planemax[i];       
    l2->varcfit[i] = varcfit[i];
    l2->npcfit[i] = npcfit[i];
  }
  for(Int_t i=0;i<4;i++){
    l2->perr[i] = perr[i];   
    l2->swerr[i] = swerr[i];  
    l2->calcrc[i] = crc[i];     
    l2->qq[i] = qq[i];  
  }

  if(CaloTrk){ //ELENA
      l2->calntrk = CaloTrk->GetEntries();  
      for(Int_t i=0;i<l2->calntrk;i++){
	  l2->caltrkseqno[i] = ((CaloTrkVar *)CaloTrk->At(i))->trkseqno;  
	  l2->ncore[i] = ((CaloTrkVar *)CaloTrk->At(i))->ncore;     
	  l2->noint[i] = ((CaloTrkVar *)CaloTrk->At(i))->noint;     
	  l2->ncyl[i] = ((CaloTrkVar *)CaloTrk->At(i))->ncyl;      
	  l2->nlast[i] = ((CaloTrkVar *)CaloTrk->At(i))->nlast;     
	  l2->npre[i] = ((CaloTrkVar *)CaloTrk->At(i))->npre;      
	  l2->npresh[i] = ((CaloTrkVar *)CaloTrk->At(i))->npresh;    
	  l2->ntr[i] = ((CaloTrkVar *)CaloTrk->At(i))->ntr;       
	  l2->planetot[i] = ((CaloTrkVar *)CaloTrk->At(i))->planetot;  
	  l2->nlow[i] = ((CaloTrkVar *)CaloTrk->At(i))->nlow;      
	  l2->qcore[i] =((CaloTrkVar *)CaloTrk->At(i))->qcore ;   
	  l2->qcyl[i] = ((CaloTrkVar *)CaloTrk->At(i))->qcyl;    
	  l2->qlast[i] = ((CaloTrkVar *)CaloTrk->At(i))->qlast;   
	  l2->qpre[i] = ((CaloTrkVar *)CaloTrk->At(i))->qpre;    
	  l2->qpresh[i] = ((CaloTrkVar *)CaloTrk->At(i))->qpresh;  
	  l2->qtr[i] = ((CaloTrkVar *)CaloTrk->At(i))->qtr;     
	  l2->qtrack[i] = ((CaloTrkVar *)CaloTrk->At(i))->qtrack;  
	  l2->qtrackx[i] = ((CaloTrkVar *)CaloTrk->At(i))->qtrackx; 
	  l2->qtracky[i] = ((CaloTrkVar *)CaloTrk->At(i))->qtracky; 
	  l2->dxtrack[i] = ((CaloTrkVar *)CaloTrk->At(i))->dxtrack; 
	  l2->dytrack[i] = ((CaloTrkVar *)CaloTrk->At(i))->dytrack; 
	  l2->qmean[i] = ((CaloTrkVar *)CaloTrk->At(i))->qmean;   
	  l2->qlow[i] = ((CaloTrkVar *)CaloTrk->At(i))->qlow;    
	  l2->dX0l[i] = ((CaloTrkVar *)CaloTrk->At(i))->dX0l;  
	  for (Int_t j=0; j<2; j++){
	      for (Int_t k=0; k<22; k++){
		  l2->tbar[i][k][j] = ((CaloTrkVar *)CaloTrk->At(i))->tbar[k][j];
	      };
	  };
      }  
  } //ELENA
}

/**
 * Returns the impact position on the top of the calorimeter as determined by the calorimeter itself.
 * @param tr : if tr = 0 use the calorimeter "normal" fit, if 1 use the calorimeter "selftrigger" fit (if any!)
**/
Float_t CaloLevel2::impx(Int_t tr){
  if ( tr == 0 ) return(cbar[0][0]);
  if ( tr == 1 ) {
    if ( !CaloTrk ) return(-110.);
    TClonesArray &t = *(CaloTrk);
    for (Int_t itrk=0; itrk<ntrk(); itrk++){
      CaloTrkVar *calotrack = (CaloTrkVar*)t[itrk];
      if ( calotrack->trkseqno == -1 ) return(calotrack->tbar[0][0]);
    };
  };
  if ( tr !=0 && tr !=1 ){
    printf(" Cannot get impx for other than calo or selftrigger tracks!\n");
  } else {
    printf(" Cannot find selftrigger block\n");
  };
  return(-100.);
};

/**
 * Returns the impact position on the top of the calorimeter as determined by the calorimeter itself.
 * @param tr : if tr = 0 use the calorimeter "normal" fit, if 1 use the calorimeter "selftrigger" fit (if any!)
**/
Float_t CaloLevel2::impy(Int_t tr){
  if ( tr == 0 ) return(cbar[0][1]);
  if ( tr == 1 ) {
    if ( !CaloTrk ) return(-110.);
    TClonesArray &t = *(CaloTrk);
    for (Int_t itrk=0; itrk<ntrk(); itrk++){
      CaloTrkVar *calotrack = (CaloTrkVar*)t[itrk];
      if ( calotrack->trkseqno == -1 ) return(calotrack->tbar[0][1]);
    };
  };
  if ( tr !=0 && tr !=1 ){
    printf(" Cannot get impy for other than calo or selftrigger tracks!\n");
  } else {
    printf(" Cannot find selftrigger block\n");
  };
  return(-100.);
};
/**
 * Should return the energy in GeV if the particle would be an electron
 * using a parametrization taken from Monte Carlo simulation
**/
void CaloLevel2::GetElectronEnergy(Float_t &energy, Float_t &sigma){
  if ( nstrip == 0 ) return;
  energy = qtot * 40.82 * 0.000106;
  sigma = 0.;
  if ( energy > 0. ) sigma = energy * (0.01183 + 0.121/sqrt(energy));
  return;
};

/**
 * Returns pointer to the set of track-related variables "itrk"
**/
CaloTrkVar *CaloLevel2::GetCaloTrkVar(Int_t itrk){
  //    
  if(itrk >= ntrk()){
    printf(" CaloLevel2 ERROR: track related variables set %i does not exists! \n",itrk);
    printf("                   stored track related variables = %i \n",ntrk());
    return(NULL);
  }
  if(!CaloTrk)return 0; //ELENA
  TClonesArray &t = *(CaloTrk);
  CaloTrkVar *calotrack = (CaloTrkVar*)t[itrk];
  return calotrack;
}
