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

#include <set>
#include "TList.h"
#include "TH1.h"

#include "QFramework/TQFolder.h"

class TQSampleVisitor;
class TQSample;
class TQCounter;

class TQSampleFolder : public TQFolder {

protected:

  void init();

  bool mergeAsSampleFolder(TQSampleFolder* f, const TString& traceID, MergeMode mode, bool verbose);

  //TList* fFriends = NULL; //!
  std::shared_ptr<std::set<TQSampleFolder*>> fFriends = nullptr; //!
  
  virtual void findFriendsInternal(TQSampleFolder* otherSF, bool forceUpdateSubFolders = false, std::shared_ptr<TList> otherSFContents = nullptr);
  void findFriends(TQSampleFolder* otherSF, bool forceUpdate, std::shared_ptr<TList> otherSFContents); //semi-internal version with additional arguments for performance reasons
  int generalizeObjectsPrivate    (TList * names, TClass* objClass, TQTaggable* options, const TString& paths, const TString& subpath);
  int generalizeObjectsPrivate    (TList * names, TClass* objClass, TQTaggable* options, const TString& subpath);
  bool fIsFindingFriends = false; //! temporary flag to prevent infinite recursions in friend finding
  bool fIsVariant = false; //!
  
public:
  static const TString restrictSelectionTagName;
  
  void convertLegacyNFs();
  void purgeWithoutTag(const TString& tag);
 
  static TQSampleFolder * newSampleFolder(TString name);
  static TQSampleFolder * loadSampleFolder(TString path, bool lazy=false);
  static TQSampleFolder * loadLazySampleFolder(const TString& path);

  static TQSampleFolder * newSampleList(const TString& name, const TString& treeLocation, double normalization = 1.);


  TQSampleFolder();
  TQSampleFolder(TString name_);

  virtual TQFolder * newInstance(const TString& name) override;

  TList * getListOfSampleFolders(const TString& path_ = "?", TClass* tclass = TQSampleFolder::Class(), bool toplevelOnly = false);
  TList * getListOfSamples(const TString& path = "*");
  int printListOfSamples(const TString& path = "*");
  
  std::vector<TString> getSampleFolderPaths(const TString& path_ = "?", TClass * tClass = NULL, bool toplevelOnly = false);
  std::vector<TString> getSampleFolderPathsWildcarded(const TString& path_ = "?", TClass * tClass = NULL, bool toplevelOnly = false);
  std::vector<TString> getSamplePaths(const TString& path_ = "?", TClass * tClass = NULL, bool toplevelOnly = false);
  std::vector<TString> getSamplePathsWildcarded(const TString& path_ = "?", TClass * tClass = NULL, bool toplevelOnly = false);

  TQSampleFolder * getSampleFolder(TString path_, TClass * tclass = 0);
  TQSampleFolder * addSampleFolder(TQSampleFolder * sampleFolder_, TString path_ = "", TClass* tclass = 0);

  TQSample * getSample(const TString& path);

  TQSampleFolder * getBaseSampleFolder();
  TQSampleFolder * getRootSampleFolder();

  std::vector<TQSampleFolder*> getSampleFoldersWithTagsEquivalentTo(const std::vector<const TQValue*>& tags);
  std::vector<TQSampleFolder*> getSampleFoldersWithTagEquivalentTo(const TQValue* tag);
  std::vector<TQSampleFolder*> getSampleFoldersWithTagEquivalentTo(const TQValue& tag);

  int getNSampleFolders(bool recursive = false);
  int getNSamples(bool recursive = false);
  
  

  TH1 * getHistogram(TString path, TString name, TQTaggable * options = nullptr, TList * sfList = 0);
  TH1 * getHistogram(TString path, TString name, TString options, TList * sfList = 0);
  TQCounter * getCounter (TString path, TString name, TString options = "", TList * sfList = 0);

  void printCounter(const TString& path, const TString& name, const TString& options = "", TList* sfList = 0);

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

  bool renameLocalObject(TString category, TClass * classType, TString oldName, TString newName);
  bool renameLocalHistogram(TString oldName, TString newName);
  bool renameLocalCounter(TString oldName, TString newName);

  int renameHistogram(TString oldName, TString newName);
  int renameCounter(TString oldName, TString newName);

  bool deleteLocalObject(TString category, TString name);
  bool deleteLocalHistogram(TString name);
  bool deleteLocalCounter(TString name);

  int deleteHistogram(TString name);
  int deleteHistograms(TString filter);
  int deleteSingleCounter(TString name);
  int deleteCounter(TString filter);

  int copyHistogram(TString source, TString destination, TString options = "");
  int copyHistograms(TString sourceFilter, TString appendix, TString options = "");

  int copyHistogramToCounter(TString source, TString destination = "");

  TList * getListOfHistogramNames (const TString& path = ".", TList * sfList = 0);
  TList * getListOfCounterNames (const TString& path = ".", TList * sfList = 0);

  void printListOfHistograms(const TString& options = "");
  void printListOfCounters (const TString& options = "");

  bool validateAllCounter(TString path1, TString path2, TString options = "");
  bool validateAllCounter(TQSampleFolder * sampleFolder, TString options = "");
  bool validateCounter(TString path1, TString path2, TString counterName, TString options = "");
  bool validateCounter(TQSampleFolder * sampleFolder, TString counterName, TString options = "", int indent = 0);

  int setScaleFactor(const TString& name, double scaleFactor, double uncertainty = 0);
  int setScaleFactor(const char* name, double scaleFactor, double uncertainty = 0);
  int setScaleFactor(const TString& name, double scaleFactor, const TString& sampleFolders);
  int setScaleFactor(const TString& name, double scaleFactor, const char* sampleFolders);
  int setScaleFactor(const TString& name, double scaleFactor, double uncertainty, const TString& sampleFolders);
  int setScaleFactor(TString name, const TString& title, double scaleFactor, double uncertainty = 0);
 
  bool getScaleFactor(const TString& path, double& scale, double& uncertainty, bool recursive = false);
  double getScaleFactor(const TString& name, bool recursive = false);
  TQCounter* getScaleFactorCounter(const TString& name);
  TQCounter* getScaleFactorCounterRecursive(const TString& name);
  TQCounter* getScaleFactorCounterInternal(TString name); 
  TQCounter* getScaleFactorCounterInternal(const TString& path, const TString& scaleScheme); //faster overload that uses much less string parsing
  void printScaleFactors(TString filter = "");

  int visitMe(TQSampleVisitor * visitor, bool requireSelectionTag=false);
  int visitSampleFolders(TQSampleVisitor * visitor, const TString& category = "?");
  int visitSampleFolders(TQSampleVisitor * visitor, const std::vector<TQSampleFolder*>& selectedFolders);
  int visitSampleFolders(TQSampleVisitor * visitor, const std::set<TQSampleFolder*>& selectedFolders);

  int generalizeHistograms (TList * names, const TString& paths, const TString& options);
  int generalizeCounters   (TList * names, const TString& paths, const TString& options);
  int generalizeHistograms (const TString& paths = "", const TString& options= "");
  int generalizeCounters   (const TString& paths = "", const TString& options= "");

  int generalizeObjects(const TString& prefix, const TString& options = "");
  int generalizeObjects(TList * names, TClass* objClass, const TString& options, const TString& paths, const TString& subpath);

  void findFriends(const TString& pathpattern, bool forceUpdate = false);
  void findFriends(TQSampleFolder* otherSF, bool forceUpdate = false);
  void findFriends(bool forceUpdate = false);

  void befriend(TQSampleFolder* other);
  void unfriend(TQSampleFolder* other);
  void clearFriends();
  void printFriends();
  int countFriends();
  bool hasFriends();
  std::shared_ptr<std::set<TQSampleFolder*>> getFriends();
  bool isFriend(TQSampleFolder* other);
  
  bool isVariant(bool recursive=true);
  void setIsVariant(bool isVariant=true) {fIsVariant=isVariant;}
  
  TString getPathFriendsWildcarded(bool requireWildcardTag = true);
  
  bool merge(TQSampleFolder * f, bool sumElements = false, bool verbose = false);
  bool merge(TQSampleFolder * f, const TString& traceID, bool sumElements = false, bool verbose = false);
  

  virtual ~TQSampleFolder();
 
  ClassDefOverride(TQSampleFolder, 3); // derived container class for data and monte carlo samples

};

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