#include <iostream>
#include <fstream>
#include <stdio.h>
//#include <vector.h>
#include <math.h>
#include <TH1F.h>
#include <TH2F.h>
#include <TH1D.h>
#include <TH2D.h>
#include <TVectorT.h>
#include <TFile.h>
#include <TROOT.h>
#include <TList.h>
#include <TString.h>
#include <TLine.h>
#include <TGraphAsymmErrors.h>
#include <TGraphErrors.h>
#include <TChain.h>
#include <TCutG.h>
#include <TF1.h>
#include <TCanvas.h>
#include <TObjString.h>
#include <TMath.h>
#include <TMVA/Timer.h>
#include <RanGen.h>


#ifndef PAMUNFOLD_H
#define PAMUNFOLD_H

using std::vector;

class PamUnfold: public TNamed{
 public:
  PamUnfold(TString name, TString title);
  ~PamUnfold();
  PamUnfold(TString name, TString title, TH1D* measured, TH2D* smearing);  //passing _measured and _smearing

  void AddExcludedBin(Int_t bin);

  TH1D* GetMeasured();
  TH2D* GetSmearing();
  TH1D* GetUnfolded();
  TList* GetBinHistList();

  void SetMeasured(TH1D*);
  void SetSmearing(TH2D*);
  void SetPrior(TH1D*);
  void SetNormalization(TH1D*);
  void SetImproved(Bool_t improv=kTRUE);
  void SetSmoothing(Bool_t smooth, TString smooth_opt="ROOT");
  void SetNsamples(UInt_t nsamples);
  void SetMaxSteps(UInt_t max_steps);
  void SetMinChi2(Double_t min_chi2);

  Bool_t IsSmNormalized();

  void Unfold();
  void ImprovedUnfold();
  void IterativeUnfolding(UInt_t niter=0, TList* list=NULL);

  void Draw(TString path);

  static void WMovAvSmooth(TH1D* input, vector<Int_t>&excl);
  static Double_t GetChi2H( TH1D* h1, TH1D* h2 );



 private:
  TH1D* _measured;
  TH1D* _unfolded;
  TH1D* _old_unfolded;
  TH2D* _smearing;
  TH2D* _smearing_sample;
  TH1D* _prior;
  TH1D* _norm;
  TList* _bin_list;
  TList* _bin_hist_list;
  Bool_t _smooth;
  TString _smooth_opt;
  UInt_t _max_steps;
  Bool_t _is_improved;
  UInt_t _nsamples;
  Double_t _min_chi2;
  vector<Int_t> _excluded_bins;
  RanGen* rangen;
  TCanvas* canv;

  Bool_t IsBinningOK(); 
  void Init();
  void NormalizeMatrix();
  void SampleMatrix();
  void BuildFlux();
  void FindSplitting(Int_t n, Int_t &nx, Int_t &ny);

  ClassDef(PamUnfold, 1);
};


#endif
