#ifndef DataProcessing_h
#define DataProcessing_h

#include <TFile.h>
#include <TSystem.h>
#include <TH1.h>
#include <TString.h>
#include <TAttMarker.h>
#include <iostream>
#include <vector>

using namespace std;

//_________________
class DataProcessing {

 public:

  DataProcessing();
  ~DataProcessing();

  void SetExpFile(const Char_t *name) {mExpFileName = name;}
  void SetMcFile(const Char_t *name)  {mMcFileName = name;}
  void SetOutFile(const Char_t *name) {mOutFileName = name;}
  void DoProcessing();
  void SetQinvBins(Int_t qInvBins, Double_t qInvLow, Double_t qInvHi) {mQinvBins=qInvBins; mQinvLow=qInvLow; mQinvHi=qInvHi;}
  void SetDetectorSelection(Int_t sel) {mDetSelection = sel;}
  void SetMultiplicityVals(Int_t vals) { mMultVals = vals; }
  void SetMultiplicityBins(Int_t bins) { mMultBins = bins; }
  void IsUseMC(Bool_t use) { mUseMC = use; }
  void IsKaon(Bool_t kaon) { mIsKaon = kaon; }
  void IsDoFit(Bool_t fit) { mDoFit = fit; }
  void ProcInt(Bool_t proc) { mProcInt = proc; }
  void ProcMult(Bool_t proc) { mProcMult = proc; }
  void ProcKt(Bool_t proc) { mProcKt = proc; }
  void SetExpStyle(Int_t color, Int_t width, Int_t style, Double_t size);
  void SetMcStyle(Int_t color, Int_t width, Int_t style, Double_t size);
  void SetCorrFctnStyle(Int_t color, Int_t width, Int_t style, Double_t size);
  void SetSourceFunction(Int_t source) {mSourceFunc = source;}
  void SetNonFemtoFunction(Int_t func) {mNonFemtoFunc = func;}
  void SetDrawLegend(Bool_t draw) {mDrawLegend = draw;}

  //
  // Functions
  //
  void OpenFiles();
  void ReadHistos();
  void ProcessHistos();
  TH1F *BuildIntegrCF(Int_t charge, Int_t refSample, Bool_t isExpData, Bool_t isKaon);
  TH1F *BuildIntegrCorrectedCF(Int_t charge, Int_t refSample, Bool_t isKaon);
  TH1F *BuildMultCF(Int_t charge, Int_t BinLo, Int_t BinHi, Int_t refSample, 
		    Bool_t isExpData, Bool_t isKaon);
  TH1F *BuildMultCorrectedCF(Int_t charge, Int_t multBin, Int_t refSample, Bool_t isKaon);
  TH1F *BuildKtCF(Int_t charge, Int_t BinLo, Int_t BinHi,
		  Int_t refSample, Bool_t isExpData, Bool_t isKaon);
  TH1F *BuildKtCorrectedCF(Int_t charge, Int_t ktBin, Int_t refSample, Bool_t isKaon);
  TH1F *BuildMultKtCF(Int_t charge, Int_t MultBinLo, Int_t MultBinHi,
		      Int_t KtBinLo, Int_t KtBinHi,
		      Int_t refSample, Bool_t isExpData, Bool_t isKaon);
  void CorrectBins(TH1F* from);
  void ProcessIntegratedHistos();
  void ProcessMultHistos();
  void ProcessKtHistos();
  void FitHistos();
  void FitUncorrectedCF();
  void FitCorrectedCF();

 private:

  void PrintFitUncorrectedParms();
  void PrintFitCorrectedParms();

  void SetExpHistoStyle(TH1* h);
  void SetMcHistoStyle(TH1* h);
  void SetHistoStyle(TH1* h);
  void Finish();

  //
  //Variables
  //
  const Char_t *mExpFileName;
  const Char_t *mMcFileName;
  const Char_t *mOutFileName;

  Int_t mQinvBins;
  Double_t mQinvLow;
  Double_t mQinvHi;

  Int_t mDetSelection;   //0-TPC, 1-TOF, 2-TPC+TOF, 3-TOF||TPC, 4-TPC+TOC(p>pthresh)||TPC(p<pthresh)

  Int_t mMultVals;
  Int_t mKtVals;

  Int_t mKtBins;
  Int_t mMultBins;

  Bool_t mUseMC;
  Bool_t mDoFit;
  Bool_t mProcInt;
  Bool_t mProcMult;
  Bool_t mProcKt;
  Bool_t mIsKaon; // true if kaons otherwise pions

  //Colors and styles
  Int_t mExpColor;
  Int_t mExpLineWidth;
  Int_t mExpMarkerStyle;
  Double_t mExpMarkerSize;

  Int_t mMcColor;
  Int_t mMcLineWidth;
  Int_t mMcMarkerStyle;
  Double_t mMcMarkerSize;

  Int_t mCorrFctnColor;
  Int_t mCorrFctnLineWidth;
  Int_t mCorrFctnMarkerStyle;
  Double_t mCorrFctnMarkerSize;

  Double_t mYaxisLo;
  Double_t mYaxisHi;

  //Fits
  Int_t mSourceFunc;
  Int_t mNonFemtoFunc;
  Bool_t mDrawLegend;

  //Files
  TFile *mExpFile;
  TFile *mMcFile;
  TFile *mOutFile;
  
  ///////////////////////////////////
  //          Input histos         //
  ///////////////////////////////////

  //Kaons
  std::vector<TH1F *> hExpKaonQinvMixNum;
  std::vector<TH1F *> hExpKaonQinvMixDen;
  std::vector<TH1F *> hExpKaonQinvRotNum;
  std::vector<TH1F *> hExpKaonQinvRotDen;
  std::vector<TH1F *> hExpKaonQinvOppNum;
  std::vector<TH1F *> hExpKaonQinvOppDen;

  std::vector<TH1F *> hExpKaonQinvKtMixNum;
  std::vector<TH1F *> hExpKaonQinvKtMixDen;
  std::vector<TH1F *> hExpKaonQinvKtRotNum;
  std::vector<TH1F *> hExpKaonQinvKtRotDen;
  std::vector<TH1F *> hExpKaonQinvKtOppNum;
  std::vector<TH1F *> hExpKaonQinvKtOppDen;

  std::vector<TH1F*> hMcKaonQinvMixNum;
  std::vector<TH1F*> hMcKaonQinvMixDen;
  std::vector<TH1F*> hMcKaonQinvRotNum;
  std::vector<TH1F*> hMcKaonQinvRotDen;
  std::vector<TH1F*> hMcKaonQinvOppNum;
  std::vector<TH1F*> hMcKaonQinvOppDen;

  //Pions
  std::vector<TH1F*> hExpPionQinvMixNum;
  std::vector<TH1F*> hExpPionQinvMixDen;
  std::vector<TH1F*> hExpPionQinvRotNum;
  std::vector<TH1F*> hExpPionQinvRotDen;
  std::vector<TH1F*> hExpPionQinvOppNum;
  std::vector<TH1F*> hExpPionQinvOppDen;

  std::vector<TH1F*> hExpPionQinvKtMixNum;
  std::vector<TH1F*> hExpPionQinvKtMixDen;
  std::vector<TH1F*> hExpPionQinvKtRotNum;
  std::vector<TH1F*> hExpPionQinvKtRotDen;
  std::vector<TH1F*> hExpPionQinvKtOppNum;
  std::vector<TH1F*> hExpPionQinvKtOppDen;

  std::vector<TH1F*> hMcPionQinvMixNum;
  std::vector<TH1F*> hMcPionQinvMixDen;
  std::vector<TH1F*> hMcPionQinvRotNum;
  std::vector<TH1F*> hMcPionQinvRotDen;
  std::vector<TH1F*> hMcPionQinvOppNum;
  std::vector<TH1F*> hMcPionQinvOppDen;

  ///////////////////////////////////
  //       Integrated over all     //
  ///////////////////////////////////

  //Kaons
  std::vector<TH1F*> hExpKaonMixIntegrCF;
  std::vector<TH1F*> hExpKaonRotIntegrCF;
  std::vector<TH1F*> hExpKaonOppIntegrCF;

  std::vector<TH1F*> hMcKaonMixIntegrCF;
  std::vector<TH1F*> hMcKaonRotIntegrCF;
  std::vector<TH1F*> hMcKaonOppIntegrCF;

  std::vector<TH1F*> hKaonMixIntegrCF;
  std::vector<TH1F*> hKaonRotIntegrCF;
  std::vector<TH1F*> hKaonOppIntegrCF;

  //Pions
  std::vector<TH1F*> hExpPionMixIntegrCF;
  std::vector<TH1F*> hExpPionRotIntegrCF;
  std::vector<TH1F*> hExpPionOppIntegrCF;

  std::vector<TH1F*> hMcPionMixIntegrCF;
  std::vector<TH1F*> hMcPionRotIntegrCF;
  std::vector<TH1F*> hMcPionOppIntegrCF;

  std::vector<TH1F*> hPionMixIntegrCF;
  std::vector<TH1F*> hPionRotIntegrCF;
  std::vector<TH1F*> hPionOppIntegrCF;

  ///////////////////////////////////
  //     Multiplicity dependece    //
  ///////////////////////////////////

  //Kaons
  std::vector<TH1F*> hExpKaonMixMultCF;
  std::vector<TH1F*> hExpKaonRotMultCF;
  std::vector<TH1F*> hExpKaonOppMultCF;

  std::vector<TH1F*> hMcKaonMixMultCF;
  std::vector<TH1F*> hMcKaonRotMultCF;
  std::vector<TH1F*> hMcKaonOppMultCF;

  std::vector<TH1F*> hKaonMixMultCF;
  std::vector<TH1F*> hKaonRotMultCF;
  std::vector<TH1F*> hKaonOppMultCF;

  //Pions
  std::vector<TH1F*> hExpPionMixMultCF;
  std::vector<TH1F*> hExpPionRotMultCF;
  std::vector<TH1F*> hExpPionOppMultCF;

  std::vector<TH1F*> hMcPionMixMultCF;
  std::vector<TH1F*> hMcPionRotMultCF;
  std::vector<TH1F*> hMcPionOppMultCF;

  std::vector<TH1F*> hPionMixMultCF;
  std::vector<TH1F*> hPionRotMultCF;
  std::vector<TH1F*> hPionOppMultCF;

  ///////////////////////////////////
  //           kT dependece        //
  ///////////////////////////////////

  //Kaons
  std::vector<TH1F*> hExpKaonMixKtCF;
  std::vector<TH1F*> hExpKaonRotKtCF;
  std::vector<TH1F*> hExpKaonOppKtCF;

  std::vector<TH1F*> hMcKaonMixKtCF;
  std::vector<TH1F*> hMcKaonRotKtCF;
  std::vector<TH1F*> hMcKaonOppKtCF;

  std::vector<TH1F*> hKaonMixKtCF;
  std::vector<TH1F*> hKaonRotKtCF;
  std::vector<TH1F*> hKaonOppKtCF;

  //Pions
  std::vector<TH1F*> hExpPionMixKtCF;
  std::vector<TH1F*> hExpPionRotKtCF;
  std::vector<TH1F*> hExpPionOppKtCF;

  std::vector<TH1F*> hMcPionMixKtCF;
  std::vector<TH1F*> hMcPionRotKtCF;
  std::vector<TH1F*> hMcPionOppKtCF;

  std::vector<TH1F*> hPionMixKtCF;
  std::vector<TH1F*> hPionRotKtCF;
  std::vector<TH1F*> hPionOppKtCF;

  //Fitted values
  //Integrated
  //Kaons
  std::vector<double> mKaonIntegrMixRadii;
  std::vector<double> mKaonIntegrMixRadiiErr;
  std::vector<double> mKaonIntegrMixLambda;
  std::vector<double> mKaonIntegrMixLambdaErr;

  std::vector<double> mKaonIntegrRotRadii;
  std::vector<double> mKaonIntegrRotRadiiErr;
  std::vector<double> mKaonIntegrRotLambda;
  std::vector<double> mKaonIntegrRotLambdaErr;

  std::vector<double> mKaonIntegrOppRadii;
  std::vector<double> mKaonIntegrOppRadiiErr;
  std::vector<double> mKaonIntegrOppLambda;
  std::vector<double> mKaonIntegrOppLambdaErr;

  //Pions
  std::vector<double> mPionIntegrMixRadii;
  std::vector<double> mPionIntegrMixRadiiErr;
  std::vector<double> mPionIntegrMixLambda;
  std::vector<double> mPionIntegrMixLambdaErr;

  std::vector<double> mPionIntegrRotRadii;
  std::vector<double> mPionIntegrRotRadiiErr;
  std::vector<double> mPionIntegrRotLambda;
  std::vector<double> mPionIntegrRotLambdaErr;

  std::vector<double> mPionIntegrOppRadii;
  std::vector<double> mPionIntegrOppRadiiErr;
  std::vector<double> mPionIntegrOppLambda;
  std::vector<double> mPionIntegrOppLambdaErr;

  //Multiplicity
  //Kaons
  std::vector<double> mKaonMultMixRadii;
  std::vector<double> mKaonMultMixRadiiErr;
  std::vector<double> mKaonMultMixLambda;
  std::vector<double> mKaonMultMixLambdaErr;

  std::vector<double> mKaonMultRotRadii;
  std::vector<double> mKaonMultRotRadiiErr;
  std::vector<double> mKaonMultRotLambda;
  std::vector<double> mKaonMultRotLambdaErr;

  std::vector<double> mKaonMultOppRadii;
  std::vector<double> mKaonMultOppRadiiErr;
  std::vector<double> mKaonMultOppLambda;
  std::vector<double> mKaonMultOppLambdaErr;

  //Pions
  std::vector<double> mPionMultMixRadii;
  std::vector<double> mPionMultMixRadiiErr;
  std::vector<double> mPionMultMixLambda;
  std::vector<double> mPionMultMixLambdaErr;

  std::vector<double> mPionMultRotRadii;
  std::vector<double> mPionMultRotRadiiErr;
  std::vector<double> mPionMultRotLambda;
  std::vector<double> mPionMultRotLambdaErr;

  std::vector<double> mPionMultOppRadii;
  std::vector<double> mPionMultOppRadiiErr;
  std::vector<double> mPionMultOppLambda;
  std::vector<double> mPionMultOppLambdaErr;

  //Kt values
  //Kaons
  std::vector<double> mKaonKtMixRadii;
  std::vector<double> mKaonKtMixRadiiErr;
  std::vector<double> mKaonKtMixLambda;
  std::vector<double> mKaonKtMixLambdaErr;

  std::vector<double> mKaonKtRotRadii;
  std::vector<double> mKaonKtRotRadiiErr;
  std::vector<double> mKaonKtRotLambda;
  std::vector<double> mKaonKtRotLambdaErr;

  std::vector<double> mKaonKtOppRadii;
  std::vector<double> mKaonKtOppRadiiErr;
  std::vector<double> mKaonKtOppLambda;
  std::vector<double> mKaonKtOppLambdaErr;

  //Pions
  std::vector<double> mPionKtMixRadii;
  std::vector<double> mPionKtMixRadiiErr;
  std::vector<double> mPionKtMixLambda;
  std::vector<double> mPionKtMixLambdaErr;

  std::vector<double> mPionKtRotRadii;
  std::vector<double> mPionKtRotRadiiErr;
  std::vector<double> mPionKtRotLambda;
  std::vector<double> mPionKtRotLambdaErr;

  std::vector<double> mPionKtOppRadii;
  std::vector<double> mPionKtOppRadiiErr;
  std::vector<double> mPionKtOppLambda;
  std::vector<double> mPionKtOppLambdaErr;
};
#endif
