#include "StHbtMaker/CorrFctn/QinvCorrFctn_MomCons.h"
#include <cstdio>
#include <sstream>

#ifdef __ROOT__ 
ClassImp(QinvCorrFctn_MomCons)
#endif

//_________________
QinvCorrFctn_MomCons::QinvCorrFctn_MomCons(char* title, const int& nbins, 
					   const float& QinvLo, const float& QinvHi) {

  mPartMass = 0.493677; //Kaon mass by default

  // set up numerator
  // title = "Num Qinv (MeV/c)";
  stringstream TitNum, TitDen;
  stringstream TitNumPt1xPt2, TitNumPt1SqrSumPt2Sqr;
  stringstream TitNumPz1xPz2, TitNumPz1SqrSumPz2Sqr;
  stringstream TitNumE1xE2, TitNumE1sumE2;

  TitNum.str("");        TitDen.str("");
  TitNumPt1xPt2.str(""); TitNumPt1SqrSumPt2Sqr.str("");
  TitNumPz1xPz2.str(""); TitNumPz1SqrSumPz2Sqr.str("");
  TitNumE1xE2.str("");   TitNumE1sumE2.str("");

  TitNum << title << "_Num";
  TitDen << title << "_Den";
  TitNumPt1xPt2 << title << "_TitNumPt1xPt2";
  TitNumPt1SqrSumPt2Sqr << title << "_TitNumPt1SqrSumPt2Sqr";
  TitNumPz1xPz2 << title << "_TitNumPz1xPz2";
  TitNumPz1SqrSumPz2Sqr << title << "_TitNumPz1SqrSumPz2Sqr";
  TitNumE1xE2 << title << "_TitNumE1xE2";
  TitNumE1sumE2 << title << "_TitNumE1sumE2";

  mNumerator = new StHbt1DHisto(TitNum.str().c_str(),
				TitNum.str().c_str(),
				nbins,QinvLo,QinvHi);

  mNumeratorPt1xPt2 = new StHbt1DHisto(TitNumPt1xPt2.str().c_str(),
				       TitNumPt1xPt2.str().c_str(),
				       nbins, QinvLo, QinvHi);

  mNumeratorPt1SqrSumPt2Sqr = new StHbt1DHisto(TitNumPt1SqrSumPt2Sqr.str().c_str(),
					       TitNumPt1SqrSumPt2Sqr.str().c_str(),
					       nbins, QinvLo, QinvHi);

  mNumeratorPz1xPz2 = new StHbt1DHisto(TitNumPz1xPz2.str().c_str(),
				       TitNumPz1xPz2.str().c_str(),
				       nbins, QinvLo, QinvHi);

  mNumeratorPz1SqrSumPz2Sqr = new StHbt1DHisto(TitNumPz1SqrSumPz2Sqr.str().c_str(),
					       TitNumPz1SqrSumPz2Sqr.str().c_str(),
					       nbins, QinvLo, QinvHi);
  mDenominator = new StHbt1DHisto(TitDen.str().c_str(),
				  TitDen.str().c_str(),
				  nbins, QinvLo, QinvHi);
  
  mNumeratorE1xE2 = new StHbt1DHisto(TitNumE1xE2.str().c_str(),
				     TitNumE1xE2.str().c_str(),
				     nbins, QinvLo, QinvHi);

  mNumeratorE1sumE2 = new StHbt1DHisto(TitNumE1sumE2.str().c_str(),
				       TitNumE1sumE2.str().c_str(),
				       nbins, QinvLo, QinvHi);

  // to enable error bar calculation...
  mNumerator->Sumw2();
  mDenominator->Sumw2();

  mNumeratorPt1xPt2->Sumw2();
  mNumeratorPt1SqrSumPt2Sqr->Sumw2();
  mNumeratorPz1xPz2->Sumw2();
  mNumeratorPz1SqrSumPz2Sqr->Sumw2();     

  mNumeratorE1xE2->Sumw2();
  mNumeratorE1sumE2->Sumw2();
}

//_________________
QinvCorrFctn_MomCons::~QinvCorrFctn_MomCons(){
  delete mNumerator;
  delete mDenominator;

  delete mNumeratorPt1xPt2;
  delete mNumeratorPt1SqrSumPt2Sqr;
  delete mNumeratorPz1xPz2;
  delete mNumeratorPz1SqrSumPz2Sqr;   
 
  delete mNumeratorE1xE2;
  delete mNumeratorE1sumE2;
}

//_________________
void QinvCorrFctn_MomCons::WriteOutHistos(){

  mNumerator->Write();
  mDenominator->Write();

  mNumeratorPt1xPt2->Write();
  mNumeratorPt1SqrSumPt2Sqr->Write();
  mNumeratorPz1xPz2->Write();
  mNumeratorPz1SqrSumPz2Sqr->Write(); 

  mNumeratorE1xE2->Write();
  mNumeratorE1sumE2->Write();
}

//_________________
void QinvCorrFctn_MomCons::Finish(){
  // here is where we should normalize, fit, etc...
  // we should NOT Draw() the histos (as I had done it below),
  // since we want to insulate ourselves from root at this level
  // of the code.  Do it instead at root command line with browser.
  //  mNumerator->Draw();
  //mDenominator->Draw();
  //mRatio->Draw();
}

//_________________
StHbtString QinvCorrFctn_MomCons::Report(){

  string stemp = "Qinv Correlation Function Report:\n";
  char ctemp[100];
  sprintf(ctemp,"Number of entries in numerator:\t%E\n",mNumerator->GetEntries());
  stemp += ctemp;
  sprintf(ctemp,"Number of entries in denominator:\t%E\n",mDenominator->GetEntries());
  stemp += ctemp;
  sprintf(ctemp,"Number of entries in numeratorPt1xPt2:\t%E\n",mNumeratorPt1xPt2->GetEntries());
  stemp += ctemp; 
  sprintf(ctemp,"Number of entries in numeratorPz1xPz2:\t%E\n",mNumeratorPz1xPz2->GetEntries());
  stemp += ctemp;   

  StHbtString returnThis = stemp;
  return returnThis;
}

//_________________
void QinvCorrFctn_MomCons::AddRealPair(const StHbtPair* pair) {

  double Qinv = fabs(pair->qInv());

  double px1 = pair->track1()->FourMomentum().x();
  double py1 = pair->track1()->FourMomentum().y();
  double pz1 = pair->track1()->FourMomentum().z();
  double E1  = ::sqrt(px1*px1 + py1*py1 + pz1*pz1 + 0.139*0.139);
  
  double px2 = pair->track2()->FourMomentum().x();
  double py2 = pair->track2()->FourMomentum().y();
  double pz2 = pair->track2()->FourMomentum().z();
  double E2  = ::sqrt(px2*px2 + py2*py2 + pz2*pz2 + mPartMass*mPartMass);
  
  double valuePt1xPt2 = (px1*px2 + py1*py2);
  double valuePt1SqrSumPt2Sqr = (px1*px1 + py1*py1 + px2*px2 + py2*py2);

  double valuePz1xPz2 = pz1*pz2;
  double valuePz1SqrSumPz2Sqr = (pz1*pz1 + pz2*pz2);
        
  mNumerator->Fill(Qinv);
  mNumeratorPt1xPt2->Fill(Qinv,valuePt1xPt2);
  mNumeratorPt1SqrSumPt2Sqr->Fill(Qinv,valuePt1SqrSumPt2Sqr);

  mNumeratorPz1xPz2->Fill(Qinv,valuePz1xPz2);
  mNumeratorPz1SqrSumPz2Sqr->Fill(Qinv,valuePz1SqrSumPz2Sqr);         

  mNumeratorE1xE2->Fill(Qinv,E1*E2);
  mNumeratorE1sumE2->Fill(Qinv,E1+E2);
}

//____________________________
void QinvCorrFctn_MomCons::AddMixedPair(const StHbtPair* pair){

  double Qinv = fabs(pair->qInv());
  mDenominator->Fill(Qinv, 1.);
}

