//this file looks like plain C, but it's actually -*- c++ -*-
#ifndef __TQ_NFCALCULATOR__
#define __TQ_NFCALCULATOR__

#include "QFramework/TQNFBase.h"

#include "TH1F.h"

#include <iostream>
#ifdef __CINT__ 
#define override
#endif
class TQNFCalculator : public TQNFBase {
public:
  enum Method {
    Single,
    FractionFitter,
    MatrixInversion,
    Unity,
    FAIL,
    UNDEFINED
  };
protected:
  int status;

  inline Method getMethod(TString name){
    name.ToLower();
    if(name == "single" || name == "simple"){
      return Single;
    }
    if(name == "fractionfitter" || name == "tfractionfitter"){
      return FractionFitter;
    }
    if(name == "matrixinversion" || name == "matrix"){
      return MatrixInversion;
    }
    if(name == "unity" || name == "1" || name == "allone" || name == "noop"){
      return Unity;
    }
    if(name == "fail"){
      return FAIL;
    }
    if(this->verbosity > 0){
      this->messages.sendMessage(TQMessageStream::ERROR,"method '%s' not implemented!",name.Data());
    }
    this->status = -50;
    return UNDEFINED;
  }

  inline TString getMethodName(TQNFCalculator::Method method){
    switch(method){
    case Single:
      return "Single";
    case FractionFitter:
      return "TFractionFitter";
    case MatrixInversion:
      return "MatrixInversion";
    case Unity:
      return "Unity";
    case FAIL:
      return "FAIL";
    default:
      return "<unknown>";
    }
    return "<unknown>";
  }

  TString defaultDataPath;
  std::vector<TString> dataPaths;
  std::vector<TString> cutNames;
  std::vector<TString> mcPaths;
  std::vector<TString> mcNames;
  std::vector<bool> mcFixed;
  std::vector<double> nfBoundUpper;
  std::vector<double> nfBoundLower;
  std::vector<double> NFs;
  std::vector<double> NFuncertainties;

  std::vector<Method> methods;

  TH1F* data;
  TObjArray* mc;

  bool initializeSelf() override;
  bool finalizeSelf() override;

  bool initializeData();
  bool initializeMC();
  size_t findIndex(TString name);

  bool ensurePositiveMC();

  size_t getFloatingSamples();

  int calculateNFs(TQNFCalculator::Method method);
  void calculateNFs_singleMode();
  void calculateNFs_TFractionFitterMode();
  void calculateNFs_MatrixMode();
  void fail();

  double epsilon;
  TQTaggable* getResultsAsTags(size_t i);

public:
  void setNFsUnity();

  void setDefaultDataPath(TString path);

  bool addRegion(TString cutName, TString myDataPath="");
  bool addSample(TString mcPath, TString name="", bool fixed=false);
  bool addSample(TString mcPath, TString name, double boundLower, double boundUpper);
  bool addFixSample(TString mcPath, TString name="");

  void printRegions(std::ostream* os = &(std::cout));
  void printSamples(std::ostream* os = &(std::cout));
  void printResults(std::ostream* os = &(std::cout));

  TString getDefaultDataPath();

  TH1* getHistogram(const TString& name);
  bool scaleSample(const TString& name, double val);

  int deployNF(const TString& name, const std::vector<TString>& startCutNames, const std::vector<TString>& stopAtCut = std::vector<TString>(), int overwrite=1, bool applyToStopCut=true);

  int deployResult(const std::vector<TString>& startCutNames, const std::vector<TString>& stopAtCut, int overwrite, bool applyToStopCut) override;

  bool addMethod(const TString& methodName);
  void clearMethods();
  void printMethods();

  bool success() override;
  int execute(int itrNumber = -1) override;
  void clear();
  int calculateNFs();
  int calculateNFs(const TString& methodName);

  TString getStatusMessage() override;
  int getStatus() override;

  void printStatus();

  double getNF(TString name);
  double getNFUncertainty(TString name);
  bool getNFandUncertainty(TString name, double& nf, double& sigma);

  const TString& getMCPath(const TString& name);
  TH1* getMCHistogram(const TString& name);

  TQSampleFolder* exportHistograms(bool postFit = true);
  bool exportHistogramsToSampleFolder(TQSampleFolder* folder, bool postFit = true);
  bool exportHistogramsToFile(const TString& destination,bool recreate = true, bool postFit = true);

  void setEpsilon(double e);
  double getEpsilon();

  int writeResultsToFile(const TString& filename);
  int writeResultsToStream(std::ostream* out);
  TString getResultsAsString(const TString& name);
  TQTaggable* getResultsAsTags(const TString& name);

  bool readConfiguration(TQFolder* f) override;

  TQNFCalculator(TQSampleFolder* f = NULL);
  TQNFCalculator(TQSampleDataReader* rd);
  virtual ~TQNFCalculator();

  ClassDef(TQNFCalculator,1) // calculator class for normalization factors

};

#endif
 TQNFCalculator.h:1
 TQNFCalculator.h:2
 TQNFCalculator.h:3
 TQNFCalculator.h:4
 TQNFCalculator.h:5
 TQNFCalculator.h:6
 TQNFCalculator.h:7
 TQNFCalculator.h:8
 TQNFCalculator.h:9
 TQNFCalculator.h:10
 TQNFCalculator.h:11
 TQNFCalculator.h:12
 TQNFCalculator.h:13
 TQNFCalculator.h:14
 TQNFCalculator.h:15
 TQNFCalculator.h:16
 TQNFCalculator.h:17
 TQNFCalculator.h:18
 TQNFCalculator.h:19
 TQNFCalculator.h:20
 TQNFCalculator.h:21
 TQNFCalculator.h:22
 TQNFCalculator.h:23
 TQNFCalculator.h:24
 TQNFCalculator.h:25
 TQNFCalculator.h:26
 TQNFCalculator.h:27
 TQNFCalculator.h:28
 TQNFCalculator.h:29
 TQNFCalculator.h:30
 TQNFCalculator.h:31
 TQNFCalculator.h:32
 TQNFCalculator.h:33
 TQNFCalculator.h:34
 TQNFCalculator.h:35
 TQNFCalculator.h:36
 TQNFCalculator.h:37
 TQNFCalculator.h:38
 TQNFCalculator.h:39
 TQNFCalculator.h:40
 TQNFCalculator.h:41
 TQNFCalculator.h:42
 TQNFCalculator.h:43
 TQNFCalculator.h:44
 TQNFCalculator.h:45
 TQNFCalculator.h:46
 TQNFCalculator.h:47
 TQNFCalculator.h:48
 TQNFCalculator.h:49
 TQNFCalculator.h:50
 TQNFCalculator.h:51
 TQNFCalculator.h:52
 TQNFCalculator.h:53
 TQNFCalculator.h:54
 TQNFCalculator.h:55
 TQNFCalculator.h:56
 TQNFCalculator.h:57
 TQNFCalculator.h:58
 TQNFCalculator.h:59
 TQNFCalculator.h:60
 TQNFCalculator.h:61
 TQNFCalculator.h:62
 TQNFCalculator.h:63
 TQNFCalculator.h:64
 TQNFCalculator.h:65
 TQNFCalculator.h:66
 TQNFCalculator.h:67
 TQNFCalculator.h:68
 TQNFCalculator.h:69
 TQNFCalculator.h:70
 TQNFCalculator.h:71
 TQNFCalculator.h:72
 TQNFCalculator.h:73
 TQNFCalculator.h:74
 TQNFCalculator.h:75
 TQNFCalculator.h:76
 TQNFCalculator.h:77
 TQNFCalculator.h:78
 TQNFCalculator.h:79
 TQNFCalculator.h:80
 TQNFCalculator.h:81
 TQNFCalculator.h:82
 TQNFCalculator.h:83
 TQNFCalculator.h:84
 TQNFCalculator.h:85
 TQNFCalculator.h:86
 TQNFCalculator.h:87
 TQNFCalculator.h:88
 TQNFCalculator.h:89
 TQNFCalculator.h:90
 TQNFCalculator.h:91
 TQNFCalculator.h:92
 TQNFCalculator.h:93
 TQNFCalculator.h:94
 TQNFCalculator.h:95
 TQNFCalculator.h:96
 TQNFCalculator.h:97
 TQNFCalculator.h:98
 TQNFCalculator.h:99
 TQNFCalculator.h:100
 TQNFCalculator.h:101
 TQNFCalculator.h:102
 TQNFCalculator.h:103
 TQNFCalculator.h:104
 TQNFCalculator.h:105
 TQNFCalculator.h:106
 TQNFCalculator.h:107
 TQNFCalculator.h:108
 TQNFCalculator.h:109
 TQNFCalculator.h:110
 TQNFCalculator.h:111
 TQNFCalculator.h:112
 TQNFCalculator.h:113
 TQNFCalculator.h:114
 TQNFCalculator.h:115
 TQNFCalculator.h:116
 TQNFCalculator.h:117
 TQNFCalculator.h:118
 TQNFCalculator.h:119
 TQNFCalculator.h:120
 TQNFCalculator.h:121
 TQNFCalculator.h:122
 TQNFCalculator.h:123
 TQNFCalculator.h:124
 TQNFCalculator.h:125
 TQNFCalculator.h:126
 TQNFCalculator.h:127
 TQNFCalculator.h:128
 TQNFCalculator.h:129
 TQNFCalculator.h:130
 TQNFCalculator.h:131
 TQNFCalculator.h:132
 TQNFCalculator.h:133
 TQNFCalculator.h:134
 TQNFCalculator.h:135
 TQNFCalculator.h:136
 TQNFCalculator.h:137
 TQNFCalculator.h:138
 TQNFCalculator.h:139
 TQNFCalculator.h:140
 TQNFCalculator.h:141
 TQNFCalculator.h:142
 TQNFCalculator.h:143
 TQNFCalculator.h:144
 TQNFCalculator.h:145
 TQNFCalculator.h:146
 TQNFCalculator.h:147
 TQNFCalculator.h:148
 TQNFCalculator.h:149
 TQNFCalculator.h:150
 TQNFCalculator.h:151
 TQNFCalculator.h:152
 TQNFCalculator.h:153
 TQNFCalculator.h:154
 TQNFCalculator.h:155
 TQNFCalculator.h:156
 TQNFCalculator.h:157
 TQNFCalculator.h:158
 TQNFCalculator.h:159
 TQNFCalculator.h:160
 TQNFCalculator.h:161
 TQNFCalculator.h:162
 TQNFCalculator.h:163
 TQNFCalculator.h:164
 TQNFCalculator.h:165
 TQNFCalculator.h:166
 TQNFCalculator.h:167
 TQNFCalculator.h:168
 TQNFCalculator.h:169
 TQNFCalculator.h:170
 TQNFCalculator.h:171