#include "QFramework/TQNFBase.h"
#include "QFramework/TQNFChainloader.h"
#include "TROOT.h"
#include "QFramework/TQNamedTaggable.h"
#include "TMath.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQLibrary.h"


#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cmath>

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQNFBase:
//
// The abstract TQNFBase class provides a common interface for custom NF calculators
// like TQNFCalculator and TQABCDCalculator. All future NF calculators should inherit
// from this class and their usage should be implemented in the TQNFChainloader.
//
////////////////////////////////////////////////////////////////////////////////////////////////

ClassImp(TQNFBase)

TQNFBase::TQNFBase() : TQNamedTaggable(),
  fReader(NULL),
  fOwnerOfReader(false),
  verbosity(1),
  infoFolder(NULL),
  cutInfoFolder(NULL),
  initialized(false),
  iterationNumber(-1)
{

}

TQNFBase::TQNFBase(const TString& name) : TQNamedTaggable(name),
                                          fReader(NULL),
                                          fOwnerOfReader(false),
                                          verbosity(1),
                                          infoFolder(NULL),
                                          cutInfoFolder(NULL),
                                          initialized(false),
                                          iterationNumber(-1)
{
  //dummy constructor
}

void TQNFBase::addNFPath(const TString& path, const TString& cutname, const TString& scalescheme){
  if(this->iterationNumber != 0) return;
  this->vNFpaths.push_back(path+"/"+scalescheme+":"+cutname); 
}

const std::vector<TString>& TQNFBase::getNFpaths() {
  // returns a reference to the current list of NF paths 
  // the actual implementation of this class must keep std::vector<TString> vNFpaths 
  // updated to contain the full paths where NFs have been deployed.
  return vNFpaths;
}

void TQNFBase::printNFPaths(){
  std::cout << TQStringUtils::makeBoldWhite(this->GetName()) << std::endl;
  for(size_t i=0; i<vNFpaths.size(); ++i){
    std::cout << vNFpaths[i] << std::endl;
  }
}

void TQNFBase::setChainLoader(TQNFChainloader* loader) {
  this->chainLoader = loader; 
}

TString TQNFBase::getPathTag(const TString& tagname){
  TString path;
  if(!this->getTagString(tagname,path)) return "";
  if(!path.BeginsWith("/")){
    return TQFolder::concatPaths(this->getTagStringDefault(tagname+".prefix", TQLibrary::getWorkingDirectory()),path);
  }
  return path;
}

bool TQNFBase::initialize(){
  if(this->initialized) return true;
  this->initialized = this->initializeSelf();
  TString logfilename = this->getPathTag("saveLog");
  if(!logfilename.IsNull()){
    this->setOutputStream(logfilename,this->verbosity);
  }
  return this->initialized;
}


bool TQNFBase::finalize(){
  this->initialized=false;
  if(this->finalizeSelf()){
    if(this->hasTag("saveLog")) this->closeOutputStream();
    return true;
  }
  if(this->hasTag("saveLog")) this->closeOutputStream();
  return false;
}

int TQNFBase::getStatus(){
  return 0;
}

TString TQNFBase::getStatusMessage(){
  return "<status unknown>";
}

int TQNFBase::deployResult(const std::vector<TString>& startAtCutNames, const std::vector<TString>& stopAtCuts ){
  // set the NF according to the desired scale scheme
  // if the tag 'targetPath' is set on this instance, it will be used to deploy the NF
  // if this tag is not set, the value of sample path used in the calculation will be used.
  //@tag:[overwrite] This object tag determines if the NFCalculator's result should overwrite an existing value (1) or if it should be set to the product of the existing and the new value(0). Default: 1 .
  //@tag:[applyToStopCut] This object tag determines if the NFCalculator's result should be applied to the stopAtCuts. Default: true.
  return this->deployResult(startAtCutNames,stopAtCuts,this->getTagIntegerDefault("overwrite",1),this->getTagBoolDefault("applyToStopCut",true));
}

void TQNFBase::setInfoFolder(TQFolder* f){
  // set the pointer to the info folder
  // where information about NFs and their respective processes
  // will be stored by the TQNFCalculator
  this->infoFolder = f;
}

void TQNFBase::setCutInfoFolder(TQFolder* f){
  // set the pointer to the cut info folder
  // where information about the cut hierarchy is stored
  // and can be read by the TQNFCalculator
  // the content of the cut info folder will not be modified
  this->cutInfoFolder = f;
}

TQNFBase::~TQNFBase(){
  if(this->fReader && this->fOwnerOfReader) delete fReader;
}

void TQNFBase::setSampleFolder(TQSampleFolder* sf){
  // set/change the base sample folder
  if(this->fReader && this->fOwnerOfReader){
    delete this->fReader;
  }
  if(sf){
    this->fReader = new TQSampleDataReader(sf);
    this->fOwnerOfReader = true;
  } else {
    this->fReader = NULL;
  } 
}

void TQNFBase::setReader(TQSampleDataReader* rd){
  // set/change the sample data reader
  if(this->fOwnerOfReader){
    delete this->fReader;
  }
  this->fReader = rd;
  this->fOwnerOfReader = false;
}

TQSampleFolder* TQNFBase::getSampleFolder(){
  // retrieve the base sample folder
  if(!this->fReader) return NULL;
  return this->fReader->getSampleFolder();
}

TQSampleDataReader* TQNFBase::getReader(){
  // retrieve the sample data reader
  return this->fReader;
}

void TQNFBase::setVerbosity(int verbosity){
  // set the verbosity level
  // 0 : silent
  // 1 : some output
  // 2 : all output
  this->verbosity = verbosity;
}

void TQNFBase::setOutputStream(const TString& outfile, int verbosity){
  // this function allows to redirect the output of the TFractionFitter
  // to an arbitrary file or device on your disk
  // including /dev/null in order to dismiss the output irreversibly
  bool ok = this->messages.open(outfile);
  if(ok) this->messages.sendMessage(TQMessageStream::INFO,"%s '%s' opening log file",this->Class()->GetName(),this->GetName());
  this->messages.sendMessage(TQMessageStream::INFO,TQUtils::getTimeStamp());
  this->messages.newline();
  this->verbosity = verbosity;
}

void TQNFBase::closeOutputStream(){
  // close the output stream assigned to this instance
  this->messages.close();
}

std::vector<TString> TQNFBase::getTargetCuts(const std::vector<TString>& startCuts, const std::vector<TString>& stopCuts, bool applyToStopCut) {
  // returns a list of all individual cuts which are in startCuts or cuts derived
  // from these, but not derived from any of stopCuts. The entries in stopCuts are
  // inclusive, i.e., these cuts are still added to the returned vector given they
  // are derived from one of the start cuts.
  std::vector<TString> retVec;
  if (!this->cutInfoFolder) {
    WARNclass("Missing cut info folder, returning an empty vector of target cuts!");
    return retVec;
  }

  TList* stopFolders = NULL;
  TList* startFolders = NULL;
  for(size_t i=0; i<startCuts.size(); ++i) {
    if (!startFolders) startFolders = new TList();
    startFolders->AddAll(this->cutInfoFolder->getListOfFolders(TString::Format("*/%s",startCuts.at(i).Data())));
  }
  for(size_t i=0; i<stopCuts.size(); ++i) {
    if (!stopFolders) stopFolders = new TList();
    stopFolders->AddAll(this->cutInfoFolder->getListOfFolders(TString::Format("*/%s",stopCuts.at(i).Data())));
  }
  
  TList* lTargets = new TList();
  TQFolderIterator itr(startFolders);
  while(itr.hasNext()) {//call worker for each starting cut
    TQFolder* f = itr.readNext();
    if (!f) continue;
    this->getTargetCutsWorker(lTargets, f, stopFolders, applyToStopCut);
  }

  //create a std::map<TQFolder*,bool> to remove duplicates
  std::map<TQFolder*,bool> map;  
  TQFolderIterator targetItr(lTargets);
  while(targetItr.hasNext()) {
    TQFolder* f = targetItr.readNext();
    if (!f) continue;
    map[f] = true;
  }
  delete lTargets;
  
  for(std::map<TQFolder*,bool>::iterator iter = map.begin(); iter != map.end(); ++iter) {
    if (!iter->first) continue;
    retVec.push_back((iter->first)->GetName());
  }
  
  return retVec;  
  
}

void TQNFBase::getTargetCutsWorker(TList* targets, TQFolder* startCut, TList* stopCuts, bool applyToStopCut) {
  //if stopCuts is a null pointer no recursion will be performed, instead startCut is simply added to targets.
  if (!startCut) return;

  if (!targets) targets = new TList();
  targets->Add(startCut);
  if (!stopCuts) return; //if there is no recursion required we stop here

  //If the current start cut is one of the stop cuts, we won't iterate any further
  TQFolderIterator stopItr(stopCuts);
  while(stopItr.hasNext()) {
    if (stopItr.readNext() == startCut) {
      return;
    } 
  }

  //Otherwise, we iterate over subfolders. In case applyToStopCut == false,
  //on each iteration, skip subFolder cuts contained in stopCuts
  TList * subFolder = startCut->getListOfFolders();
  TQFolderIterator subItr(subFolder);
  bool flagSubFolder;
  while(subItr.hasNext()) {
    TQFolder* f = subItr.readNext();
    flagSubFolder = false;

    if (!applyToStopCut){
      for(const auto&& stopCutName: *stopCuts){
	if (f->GetName() == stopCutName->GetName()){
	  flagSubFolder = true;
	  break;
	}
      }
      if (!flagSubFolder){
	this->getTargetCutsWorker(targets, f, stopCuts, applyToStopCut);
      }
    }
    else{
      this->getTargetCutsWorker(targets, f, stopCuts, applyToStopCut);
    }
  }
  
  return;
}












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