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

#include "TFolder.h"
#include "TClass.h"
#include "TDirectory.h"
#include <set>

#include "QFramework/TQFlags.h"
#include "QFramework/TQTaggable.h"


class TQFolder : public TFolder, public TQTaggable {
 
protected:

  enum MergeMode {
    PreferThis = 0,
    SumElements = 1,
    PreferOther = 2
  };
  
  TDirectory* fMyDir; //!
  bool fOwnMyDir; //!
  TString fExportName; //!
  TQFolder * fBase;
  // isFullyResolved is meant to reflect
  // the state of all subfolders as well
  // w.r.t. whether there exist any
  // unresolved import links
  bool isFullyResolved; //!

  bool fIsEquivalentToSnapshot; //!
 
  virtual TObject * importObjectFromDirectory(TDirectory * dir, TString importPath, bool recurse=true, TClass* expectedClass=NULL);

  virtual bool split(TDirectory * dir, int depth);
  bool writeFolderInternal(TDirectory * dir, const TString& exportName, int depth, bool keepInMemory);
  virtual bool writeFolderHook(TDirectory * dir, const TString& exportName, int depth, bool keepInMemory);  
 
  virtual bool importFromTextPrivate(TString input, int &nNewlines, TString &errFile, TString &errMsg);
  virtual bool importFromTextFilePrivate(const TString& filename_, int &nNewlines, TString &errFile, TString &errMsg);
 
  void setBase(TQFolder * base_);
  void setDirectoryInternal(TDirectory* dir);
  void clearDirectoryInternal();
  bool writeContentsToHTML(std::ostream& out, int expandDepth, bool includeUntextables);

  void printInternal(TString options, int indent, bool resolve=true);
  bool printDiff(TQFolder * f, TQTaggable& options, int indent);
  void mergeObjects(TQFolder* other, MergeMode mode);
  bool mergeAsFolder(TQFolder* other, MergeMode mode);

  
  void getFoldersWithTagEquivalentToInternal(const TQValue* tag, std::vector<TQFolder*>& matches);
  
  //templated functions need to be visible to the compiler when we use it
  //so this needs to be in the header (or included from there) to avoid having 
  //to explicitly instantiate different template resolutions
  template<class T> int searchObjectsInternal(std::set<T*>& wanted, std::set<T*>& found) {
    int nFound = 0;
    TIterator* itr = fFolders->MakeIterator();
    TObject* obj = itr->Next();
    T* tobj = dynamic_cast<T*>(obj);
    while(obj){
      tobj = dynamic_cast<T*>(obj);
      if(tobj){
        for (T* fugative : wanted) {
          if (fugative == tobj) {
            found.insert(fugative);
            wanted.erase(fugative);
            ++nFound;
            break;
          }
        }
      }
      //if we have a TQFolder we recurse
      if (obj->InheritsFrom(TQFolder::Class()))  {
        TQFolder* f = static_cast<TQFolder*>(obj);
        nFound += f->searchObjectsInternal(wanted,found);
      }
      obj = itr->Next();
    }
    delete itr;
    return nFound;
  }//end seachObjectsInternal
  
public:

  // static string processing
  static bool parseDestination(TString dest, TString &path, TString &newName);
  static bool parseLocation(TString importpath, TString& filename, TString& objname);
  static TString makeExportName(TString exportName);

  static const TString& getValidNameCharacters();
  static bool isValidName(const TString& name);
  static bool isValidPath(TString path, bool allowRelativePaths = true, bool allowWildcards = true, bool allowArithmeticStringExpressions = false);
  static TString makeValidIdentifier(TString identifier, TString replacement = "");
  static TString makeValidPath(TString path, TString replacement = "", bool allowRelativePaths = true, bool allowWildcards = true);
 
  static TString getPathHead (TString &path);
  static TString getPathTail (TString &path);
  static TString getPathWithoutHead (TString path);
  static TString getPathWithoutTail (TString path);
 
  static TString concatPaths(TString path1, TString path2);
  static TString concatPaths(const TString& path1, const TString& path2, const TString& path3);
  static TString concatPaths(const TString& path1, const TString& path2, const TString& path3, const TString& path4);
  static TString concatPaths(const TString& path1, const TString& path2, const TString& path3, const TString& path4, const TString& path5);  
 
  static int countPathLevels(TString path, bool checkPathTokens = true);
 
  // directory handling and laziness
  void autoSetExportName();
  void autoSetExportNames();
  void setExportName(const TString& name);
  const TString& getExportName();
  int setDirectory(TDirectory* dir = gDirectory, bool own=false);
  TDirectory* getDirectory();
  bool isOnDisk(TDirectory* dir);
  bool isOnDisk();
  bool isLazy();
  bool collapse();
 
  int resolveImportLinks(bool recurse=true);
  TObject * resolveImportLink(const TString& linkName, bool recurse=true);
  int resolveImportLinks(TDirectory * dir, bool recurse=true);
  TObject * resolveImportLink(const TString& linkName, TDirectory * dir, bool recurse=true);

  // static helpers
  static TFile* openFile(TString& importPath, const TString& opt = "READ");
  static TQFolder * newFolder(TString name);
  static TQFolder * loadLazyFolder(TString path);
  static TQFolder * loadFolder(TString path, bool lazy=false);
  static TQFolder * loadFromTextFile(TString filename, bool showErrorMessage = false);
  static TQFolder * loadFromTextFile(TString filename, TString &errorMessage);
 
  static TQFolder * copyDirectoryStructureLocal(const TString& basepath, int maxdepth = 999);
  static TQFolder * copyDirectoryStructureEOS (const TString& basepath, int maxdepth = 999);
  static TQFolder * copyDirectoryStructure (const TString& basepath, int maxdepth = 999);

  // basic class functionality
  TQFolder();
  TQFolder(const TString& name);
  virtual ~TQFolder();

  virtual TQFolder * newInstance(const TString& name);

  TString getName() const;
  void setName(const TString& newName);
  const TString& getNameConst() const;

  TString getPath();
  TString getPathWildcarded();
  TQFolder * getBase(int depth = 1) const;
  TQFolder * getRoot();
  bool isRoot();
  int getDistToRoot() const;
  int getDepth();
  int areRelated(const TQFolder* other) const;
  TList * getTraceToRoot(bool startAtRoot = false);
  bool isBaseOf(TQFolder * folder);
  TQFolder * detachFromBase();

  bool checkConsistency(bool verbose = false);
  virtual int sortByName();
  virtual void sortByNameRecursive();

  virtual int getOwnSize() const;  
  virtual int getSize(bool memoryOnly = true);
  virtual TString getSizeAsString(bool memoryOnly = true);
  bool isEmpty() const;
 
  // tag handling
  virtual TQTaggable * getBaseTaggable() const override;
  virtual TList * getDescendantTaggables() override;
  virtual TList * getListOfTaggables(const TString& taggables) override;
  virtual TList * getTaggablesByName(const TString& taggables) override;

  bool executeCopyCommand(TString object, TString& errMsg, bool moveOnly, const TString& destPrefix = "");

  void setInfoTags();
 
  // advanced functionality
  virtual bool isEquivalentTo(TQFolder * f, const TString& options = "");
  virtual bool isEquivalentTo(TQFolder * f, TQTaggable& options);

  bool printDiff(const TString& path1, const TString& path2, const TString& options = "");
  bool printDiff(TQFolder * f, const TString& options = "");

  bool merge(TQFolder* other, bool sumElements=false);
  bool mergeTags(TQFolder* other);

  TQFolder* findCommonBaseFolder(TCollection* fList, bool allowWildcards=true);

  // pretty-print
  void print(const TString& options = "");
  void printContents(const TString& options = "");

  // working with the folder structure
  TList * getListOfFolders(const TString& path_ = "?", TClass * tclass = TQFolder::Class(), bool toplevelOnly = false, bool firstMatchOnly = false);
  TList * getListOfObjects(TString path_ = "?", TClass * tclass = TObject::Class());
  TList * getListOfObjectPaths(TString path_ = "?", TClass * tclass = TObject::Class());
  
  std::vector<TQFolder*> getFoldersWithTagsEquivalentTo(const std::vector<const TQValue*>& tags);
  std::vector<TQFolder*> getFoldersWithTagEquivalentTo(const TQValue* tag);
  std::vector<TQFolder*> getFoldersWithTagEquivalentTo(const TQValue& tag);

  std::vector<TString> getFolderPaths(const TString& path_ = "?", TClass * tClass = TQFolder::Class(), bool toplevelOnly = false);
  std::vector<TString> getFolderPathsWildcarded(const TString& path_ = "?", TClass * tClass = TQFolder::Class(), bool toplevelOnly = false);
  
  TQFolder * getFolder(const TString& path_, TClass * tclass);
  TQFolder * getFolder(const TString& path);
  TQFolder * getFolder(const char* path);
  TQFolder * addFolder(TQFolder * folder_, TString path_ = "", TClass * tclass = 0);
 
  TList * getListOfObjectNames(TClass * class_ = 0, bool recursive = false, TString path_ = "");
  TObject * getObject(const TString& name_, const TString& path_ = "");
  TObject * getCopyOfObject(const TString& name_, const TString& path_ = "");
  TString getObjectPath(TString name_);
  TList* getObjectPaths(TString namepattern, TString pathpattern = "./", TClass* objClass = TObject::Class()); 

  virtual TQFolder * addObject(TObject * object, TString destination = "", TClass* folderClass = TQFolder::Class());
  virtual TQFolder * addCopyOfObject(TObject * object, TString destination = "", TClass* folderClass = TQFolder::Class());

  virtual bool hasObject(TString name);

  virtual bool removeObject(const TString& name);
  virtual int deleteObject(TString name, bool removeOnly = false, TClass *tclass = 0);
  virtual int deleteAll();

  virtual bool moveTo(TQFolder * dest, const TString& newName = "");
  virtual bool moveTo(const TString& dest);
  virtual bool moveFolder(const TString& source, const TString& dest);

  virtual TQFolder * copy(const TString& newName = "");

  virtual TQFolder * copyTo(TQFolder * dest);
  virtual TQFolder * copyTo(const TString& dest);
  virtual TQFolder * copyFolder(const TString& source, const TString& dest);

  virtual int getNElements(bool recursive = false, TClass * class_ = 0);
  virtual int getNObjects(const TString& nameFilter, bool recursive);
  virtual int getNObjects(const TString& nameFilter = "") const;  
  
  template<class T> int searchObjects(const std::set<T*>& wanted, std::set<T*>& found) {
    std::set<T*> wanted_ = wanted;
    return this->searchObjectsInternal(wanted_,found);
  }
  
  // file I/O
  virtual bool writeDirectory(TDirectory * baseDir);
  virtual bool writeUpdate(int depth = -1, bool keepInMemory = true);
  virtual bool writeFolder(TDirectory * dir, TString name, int depth = -1, bool keepInMemory = true);
  virtual bool writeFolderMaxSize(TDirectory * dir, TString name, int maxSizeInMB = 10, bool keepInMemory = true);
  virtual bool writeFolder(TDirectory * dir, int depth = -1, bool keepInMemory = true);
  virtual bool writeFolderMaxSize(TDirectory * dir, int maxSizeInMB = 10, bool keepInMemory = true);
  virtual int writeToFile(const TString& filename, bool overwrite = 0, int depth=-1, bool keepInMemory = true);

  virtual TList * exportToText(bool includeUntextables = false, int indent = 0);
  virtual bool exportToTextFile(const TString& filename, bool includeUntextables = false);
  virtual TList * exportTagsToText(const TString& filter);
  virtual bool exportTagsToTextFile(const TString& filename, const TString& filter);

  virtual TObject * importObject(TString importPath, bool recurse=true);

  bool exportToHTMLFile(const TString& filename, int expandDepth = 1, bool includeUntextables=true);

  virtual bool importFromText(const TString& input);
  virtual bool importFromText(const TString& input, TString &errorMessage);
  virtual bool importFromTextFile(const TString& filename);
  virtual bool importFromTextFile(const TString& filename, TString &errorMessage);
  virtual bool importFromTextFiles(const TString& filePattern);
  virtual bool importFromTextFiles(const TString& filePattern, TString &errorMessage);

  //expanded functionality for TQFolder (basic version can be found in TQTaggable)
  int replaceInFolderTags(TQTaggable& params, const TString& path, const TString& tagFilter = "*", TClass* typeFilter = TQFolder::Class() );

  // ROOT related functions

  virtual int Compare(const TObject * obj) const override;
  virtual bool IsSortable() const override;
  ClassDefOverride(TQFolder, 1); // container class for all types of objects and meta-information

};

#endif

 TQFolder.h:1
 TQFolder.h:2
 TQFolder.h:3
 TQFolder.h:4
 TQFolder.h:5
 TQFolder.h:6
 TQFolder.h:7
 TQFolder.h:8
 TQFolder.h:9
 TQFolder.h:10
 TQFolder.h:11
 TQFolder.h:12
 TQFolder.h:13
 TQFolder.h:14
 TQFolder.h:15
 TQFolder.h:16
 TQFolder.h:17
 TQFolder.h:18
 TQFolder.h:19
 TQFolder.h:20
 TQFolder.h:21
 TQFolder.h:22
 TQFolder.h:23
 TQFolder.h:24
 TQFolder.h:25
 TQFolder.h:26
 TQFolder.h:27
 TQFolder.h:28
 TQFolder.h:29
 TQFolder.h:30
 TQFolder.h:31
 TQFolder.h:32
 TQFolder.h:33
 TQFolder.h:34
 TQFolder.h:35
 TQFolder.h:36
 TQFolder.h:37
 TQFolder.h:38
 TQFolder.h:39
 TQFolder.h:40
 TQFolder.h:41
 TQFolder.h:42
 TQFolder.h:43
 TQFolder.h:44
 TQFolder.h:45
 TQFolder.h:46
 TQFolder.h:47
 TQFolder.h:48
 TQFolder.h:49
 TQFolder.h:50
 TQFolder.h:51
 TQFolder.h:52
 TQFolder.h:53
 TQFolder.h:54
 TQFolder.h:55
 TQFolder.h:56
 TQFolder.h:57
 TQFolder.h:58
 TQFolder.h:59
 TQFolder.h:60
 TQFolder.h:61
 TQFolder.h:62
 TQFolder.h:63
 TQFolder.h:64
 TQFolder.h:65
 TQFolder.h:66
 TQFolder.h:67
 TQFolder.h:68
 TQFolder.h:69
 TQFolder.h:70
 TQFolder.h:71
 TQFolder.h:72
 TQFolder.h:73
 TQFolder.h:74
 TQFolder.h:75
 TQFolder.h:76
 TQFolder.h:77
 TQFolder.h:78
 TQFolder.h:79
 TQFolder.h:80
 TQFolder.h:81
 TQFolder.h:82
 TQFolder.h:83
 TQFolder.h:84
 TQFolder.h:85
 TQFolder.h:86
 TQFolder.h:87
 TQFolder.h:88
 TQFolder.h:89
 TQFolder.h:90
 TQFolder.h:91
 TQFolder.h:92
 TQFolder.h:93
 TQFolder.h:94
 TQFolder.h:95
 TQFolder.h:96
 TQFolder.h:97
 TQFolder.h:98
 TQFolder.h:99
 TQFolder.h:100
 TQFolder.h:101
 TQFolder.h:102
 TQFolder.h:103
 TQFolder.h:104
 TQFolder.h:105
 TQFolder.h:106
 TQFolder.h:107
 TQFolder.h:108
 TQFolder.h:109
 TQFolder.h:110
 TQFolder.h:111
 TQFolder.h:112
 TQFolder.h:113
 TQFolder.h:114
 TQFolder.h:115
 TQFolder.h:116
 TQFolder.h:117
 TQFolder.h:118
 TQFolder.h:119
 TQFolder.h:120
 TQFolder.h:121
 TQFolder.h:122
 TQFolder.h:123
 TQFolder.h:124
 TQFolder.h:125
 TQFolder.h:126
 TQFolder.h:127
 TQFolder.h:128
 TQFolder.h:129
 TQFolder.h:130
 TQFolder.h:131
 TQFolder.h:132
 TQFolder.h:133
 TQFolder.h:134
 TQFolder.h:135
 TQFolder.h:136
 TQFolder.h:137
 TQFolder.h:138
 TQFolder.h:139
 TQFolder.h:140
 TQFolder.h:141
 TQFolder.h:142
 TQFolder.h:143
 TQFolder.h:144
 TQFolder.h:145
 TQFolder.h:146
 TQFolder.h:147
 TQFolder.h:148
 TQFolder.h:149
 TQFolder.h:150
 TQFolder.h:151
 TQFolder.h:152
 TQFolder.h:153
 TQFolder.h:154
 TQFolder.h:155
 TQFolder.h:156
 TQFolder.h:157
 TQFolder.h:158
 TQFolder.h:159
 TQFolder.h:160
 TQFolder.h:161
 TQFolder.h:162
 TQFolder.h:163
 TQFolder.h:164
 TQFolder.h:165
 TQFolder.h:166
 TQFolder.h:167
 TQFolder.h:168
 TQFolder.h:169
 TQFolder.h:170
 TQFolder.h:171
 TQFolder.h:172
 TQFolder.h:173
 TQFolder.h:174
 TQFolder.h:175
 TQFolder.h:176
 TQFolder.h:177
 TQFolder.h:178
 TQFolder.h:179
 TQFolder.h:180
 TQFolder.h:181
 TQFolder.h:182
 TQFolder.h:183
 TQFolder.h:184
 TQFolder.h:185
 TQFolder.h:186
 TQFolder.h:187
 TQFolder.h:188
 TQFolder.h:189
 TQFolder.h:190
 TQFolder.h:191
 TQFolder.h:192
 TQFolder.h:193
 TQFolder.h:194
 TQFolder.h:195
 TQFolder.h:196
 TQFolder.h:197
 TQFolder.h:198
 TQFolder.h:199
 TQFolder.h:200
 TQFolder.h:201
 TQFolder.h:202
 TQFolder.h:203
 TQFolder.h:204
 TQFolder.h:205
 TQFolder.h:206
 TQFolder.h:207
 TQFolder.h:208
 TQFolder.h:209
 TQFolder.h:210
 TQFolder.h:211
 TQFolder.h:212
 TQFolder.h:213
 TQFolder.h:214
 TQFolder.h:215
 TQFolder.h:216
 TQFolder.h:217
 TQFolder.h:218
 TQFolder.h:219
 TQFolder.h:220
 TQFolder.h:221
 TQFolder.h:222
 TQFolder.h:223
 TQFolder.h:224
 TQFolder.h:225
 TQFolder.h:226
 TQFolder.h:227
 TQFolder.h:228
 TQFolder.h:229
 TQFolder.h:230
 TQFolder.h:231
 TQFolder.h:232
 TQFolder.h:233
 TQFolder.h:234
 TQFolder.h:235
 TQFolder.h:236
 TQFolder.h:237
 TQFolder.h:238
 TQFolder.h:239
 TQFolder.h:240
 TQFolder.h:241
 TQFolder.h:242
 TQFolder.h:243
 TQFolder.h:244
 TQFolder.h:245
 TQFolder.h:246
 TQFolder.h:247
 TQFolder.h:248
 TQFolder.h:249
 TQFolder.h:250
 TQFolder.h:251
 TQFolder.h:252
 TQFolder.h:253
 TQFolder.h:254
 TQFolder.h:255
 TQFolder.h:256
 TQFolder.h:257
 TQFolder.h:258
 TQFolder.h:259
 TQFolder.h:260
 TQFolder.h:261
 TQFolder.h:262
 TQFolder.h:263
 TQFolder.h:264
 TQFolder.h:265
 TQFolder.h:266
 TQFolder.h:267
 TQFolder.h:268
 TQFolder.h:269
 TQFolder.h:270
 TQFolder.h:271
 TQFolder.h:272
 TQFolder.h:273
 TQFolder.h:274
 TQFolder.h:275
 TQFolder.h:276
 TQFolder.h:277
 TQFolder.h:278
 TQFolder.h:279
 TQFolder.h:280
 TQFolder.h:281
 TQFolder.h:282
 TQFolder.h:283
 TQFolder.h:284
 TQFolder.h:285
 TQFolder.h:286
 TQFolder.h:287
 TQFolder.h:288
 TQFolder.h:289