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

class TH1;
class THnBase;
class TGraph;
class TGraph2D;
class TTree;
class TProfile;
#include "TStopwatch.h"

#include "QFramework/TQSampleFolder.h"
#include "QFramework/TQTaggable.h"
#include "QFramework/TQCounter.h"
#include "QFramework/TQPCA.h"
#include "QFramework/TQTable.h"
#include "QFramework/TQMessageStream.h"
#include <vector>
#include <sstream>

class TQSampleDataReader {

public:

  // Helper struct to be used when performing path arithmetic
  struct PathTerm {
    double factor;
    TString path;
    double statCor;
    PathTerm():factor(1.),path(""),statCor(1.){}
    PathTerm(double f, TString p, double s) {
      factor = f;
      path = p;
      statCor = s;
    }
  };

  typedef std::vector<PathTerm> AltPath_t; // EXCLUDE

protected:
  
  TQSampleFolder * f_baseSampleFolder;
  bool f_localMode;
  TQMessageStream f_errMsg;

  TString f_styleScheme;
  TString f_filterScheme;
  TString f_normScheme;
  TString f_scaleScheme;
 
  TString f_pathHistograms;
  TString f_pathGraphs;
  TString f_pathGridScan;
  TString f_pathCutflow;
  TString f_pathEventlists;
  TString f_pathScaleFactors;
  TString f_pathPCA;
  TString f_pathTrees;
  
  bool f_applyStyles = true;
  
  int f_Verbose;
  int f_maxCorrWarnings = 25;
  
  std::map<TString,TQFolder*> f_identifierToFolderMap;

  void setErrorMessage(const TString& fname, const TString& message);

  template<class T> TList * collectElements(AltPath_t& paths, AltPath_t& elements, const TString& subPath, /*TQCounter * scale,*/ TList * sfList, TQTaggable * options);
  template<class T> int collectElementsWorker(TQSampleFolder * sampleFolder, const TString& elementName, const TString& subPath, TList* list, TList * baseScaleList, TList * sfList, TQTaggable * options, int indent);

  template<class T> int sumElements( TList * list, T * &histo, TQTaggable * options );
  int sumElements( TList * list, TQCounter* &counter, TQTaggable * options );
  int sumElements( TList * list, TQTable * &table, TQTaggable * options );
  int sumElements( TList * list, TGraph * &graph, TQTaggable * options );
  int sumElements( TList * list, TGraph2D * &graph, TQTaggable * options );
  int sumElements( TList * list, TTree * &tree, TQTaggable * options );
  int sumElements( TList * list, TQPCA * &tree, TQTaggable * options );
  int sumElements( TList * list, THnBase * &histo, TQTaggable * options );
  
  void addObjectNames(TQSampleFolder * sampleFolder, const TString& objectPath, TClass * objectClass,
                      TList * &objectNames, TList * sfList, const TString& filterScheme);
 
  void addObjectNames(const TString& path, const TString& objectPath, TClass * objectClass,
                      TList * &objectNames, TList * sfList, const TString& filterScheme);

  TList * getBaseScaleFactors(TQSampleFolder * sampleFolder, const TString& path, const TString& scaleScheme);
  TList * getListOfSampleFoldersTrivial(TString path, TClass* tclass=NULL);

  template<class T>
  T * getElement(const TString& path, const TString& name, const TString& subPath, TQTaggable * options, TList * sfList = NULL);
 
  template<class T>
  int getElementWorker(AltPath_t& paths, AltPath_t& elements, T*&element, const TString& subPath, TList* sfList, TQTaggable* options);

 
public:
  TStopwatch * collectTimer = nullptr;
  TStopwatch * summationTimer = nullptr;
  TStopwatch * auxTimer = nullptr;
  
  void setDefaultScaleScheme(const TString& defaultScheme);
  
  inline void setApplyStyles(bool doApply=true) {this->f_applyStyles = doApply;}
  inline bool getApplyStyles() {return this->f_applyStyles;}
  
  void applyStyleToElement(TObject* element, TCollection* sfList, TQTaggable* options = NULL);

  std::vector<TString> getPaths(const TString& paths, TList * inputTokens = 0, const TString& pathPrefix = "");  
  std::vector<AltPath_t> parsePaths(TString paths, TList * inputTokens = 0, TString pathPrefix = "");
  std::vector< std::vector<TString> > getParsedPathStrings(TString paths, TList * inputTokens = 0, TString pathPrefix = "");

  TList * getListOfSampleFolders(const TString& path, TClass* tclass = TQSampleFolder::Class());

  TObject * getElement(const TString& path, const TString& name, TClass* objClass, const TString& subPath, TQTaggable * options, TList * sfList = NULL);

  TQSampleDataReader();
  TQSampleDataReader(TQSampleFolder * sampleFolder);

  void printPaths(TString paths);

  void reset();

  void setLocalMode(bool localMode = false);
  bool getLocalMode();

  void setVerbose(int verbose);
  int getVerbose();

  TString getErrorMessage();

  TQSampleFolder* getSampleFolder();

  bool compareHistograms(const TString& histName1, const TString& histName2, const TString path = "*", double maxdiff = 0.01, bool print = true);
  
  bool areFoldersCorrelated(TQFolder* f1, TQFolder* f2, double& correlation, bool reversed = false);
  bool areFoldersCorrelated(TQFolder* f1, TQFolder* f2);
  
  TString getStoragePath(TQFolder* f);
  
  TQFolder* getCorrelationFolderByIdentifier(const TString& id, bool forceUpdate=false);

  void processHistogramOptions(TH1*& histo, TQTaggable* options);
  
  virtual bool passesFilter(TQSampleFolder * sampleFolder, TString filterName);

  virtual TH1 * getRatesHistogram(const TString& path, TString name, TQTaggable * options, TList * sfList = 0);
  virtual TH1 * getRatesHistogram(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual TProfile * getProfile(const TString& path, TString name, TQTaggable * options, TList * sfList = 0);
  virtual TProfile * getProfile(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual TH1 * getHistogram(const TString& path, TString name, TQTaggable * options = nullptr, TList * sfList = 0);
  virtual TH1 * getHistogram(const TString& path, const TString& name, const TString& options, TList * sfList = 0);
  virtual TGraph * getGraph(const TString& path, TString name, TQTaggable * options, TList * sfList = 0);
  virtual TGraph * getGraph(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual TGraph2D * getGraph2D(const TString& path, TString name, TQTaggable * options, TList * sfList = 0);
  virtual TGraph2D * getGraph2D(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual THnBase * getTHnBase(const TString& path, TString name, TQTaggable * options, TList * sfList = 0);
  virtual THnBase * getTHnBase(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual TQCounter * getCounter (const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual TQCounter * getCounter (const TString& path, const TString& name, TQTaggable* options, TList * sfList = 0);
  virtual TQPCA*getPCA (const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);
  virtual TQPCA*getPCA (const TString& path, const TString& name, TQTaggable* options, TList * sfList = 0);
  virtual TQTable * getEventlist(const TString& path, const TString& name, TQTaggable * options, TList * sfList = 0);
  virtual TQTable * getEventlist(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);

  virtual TTree * getTree(const TString& path, const TString& name, TQTaggable * options, TList * sfList = 0);
  virtual TTree * getTree(const TString& path, const TString& name, const TString& options = "", TList * sfList = 0);


  virtual bool hasHistogram(const TString& path, const TString& name, const TString& options = "");
  virtual bool hasCounter (const TString& path, const TString& name, const TString& options = "");

  virtual TList * getListOfHistogramNames (const TString& path = ".", TList * sfList = 0);
  virtual TList * getListOfCounterNames (const TString& path = ".", TList * sfList = 0);
  virtual TList * getListOfEventlistNames (const TString& path = ".", TList * sfList = 0);
  virtual TList * getListOfObjectNames (TClass* objClass, const TString& subpath, const TString& path = ".", TList * sfList=0);

  virtual void printListOfHistograms (TString options = "");
  virtual void printListOfHistogramLocations(const TString& name);
  virtual void printListOfCounters (TString options = "");
  virtual void printListOfCounterLocations(const TString& name);

  virtual bool exportHistograms(TDirectory* d, const TString& sfpath, const TString& tags = "");
  virtual bool exportHistograms(TDirectory* d, const TString& sfpath, TQTaggable& tags);
  virtual TFolder* exportHistograms(const TString& sfpath, const TString& tags = "");
  virtual TFolder* exportHistograms(const TString& sfpath, TQTaggable& tags);
  virtual bool exportHistogramsToFile(const TString& fname, const TString& sfpath, const TString& tags = "");
  virtual bool exportHistogramsToFile(const TString& fname, const TString& sfpath, TQTaggable& tags);

  virtual void copyData(const TString& source, const TString&target, const TString&options = "");

  virtual ~TQSampleDataReader();
 
  ClassDef(TQSampleDataReader, 1); // helper class for data retrieval from sample folders

};

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