#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <vector>
#include <iterator>

#include "SFramework/TSStatisticsManager.h"
#include "SFramework/TSStatisticsPlotter.h"

#include "TSystem.h"
#include "TParameter.h"
#include "Math/ProbFuncMathCore.h"
#include "Math/QuantFuncMathCore.h"

#include "QFramework/TQSampleFolder.h"
#include "QFramework/TQStringUtils.h"
#include "QFramework/TQHistogramUtils.h"
#include "QFramework/TQSampleDataReader.h"
#include "QFramework/TQTaggable.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQIteratorT.h"
#include "QFramework/TQFolder.h"
#include "QFramework/TQPathManager.h"

// #define _DEBUG_
#include "QFramework/TQLibrary.h"

ClassImp(TSStatisticsManager)

typedef std::map<const std::string,const TSStatisticsManager::Action*> ActionList;

namespace {
  inline ActionList& Actions(){
    static ActionList sActions;
    return sActions;
  }
}

//__________________________________________________________________________________|___________

int TSStatisticsManager::Action::perform(TQFolder* config, TSStatisticsManager* m) const {
  // apply this action
  if(!config){
    throw std::runtime_error("invalid config passed to statistics manager!");
  }
  TQFolderIterator itr(config->getListOfFolders("?"));
  this->manager = m;
  bool content = false;
  size_t nerr = 0;
  while(itr.hasNext()){
    TQFolder* c = itr.readNext();
    if(!c){
      throw std::runtime_error("invalid NULL configuration!");
    }
    content = true;
    if(!this->execute(c)){
      if(c->getTagBoolDefault("breakOnError",false)){
	BREAKclass("unable to perform action '%s'",config->GetName());
      } else {
	ERRORclass("unable to perform action '%s'",config->GetName());
	++nerr;
      }
    }
  }
  this->manager = NULL;
  if(!content){
    ERRORclass("action '%s' has no content!",config->GetName());
  }
  return nerr;
}

//__________________________________________________________________________________|___________

TQFolder* TSStatisticsManager::Action::models () const{
  return manager->getModels();
}

//__________________________________________________________________________________|___________

TQFolder* TSStatisticsManager::Action::workspaces () const{
  return manager->getWorkspaces();
}

//__________________________________________________________________________________|___________

TQFolder* TSStatisticsManager::Action::results () const{
  return manager->getResults();
}

//__________________________________________________________________________________|___________

bool TSStatisticsManager::registerAction(const Action* a, const char* name){
  Actions()[name] = a;
  return true;
}

//__________________________________________________________________________________|___________

const std::map<const std::string,const TSStatisticsManager::Action*>& TSStatisticsManager::getActions() {
  return Actions();
}

//__________________________________________________________________________________|___________

void TSStatisticsManager::printActions(){
  for(auto a:Actions()){
    std::cout << a.first << std::endl;
  }
}

//__________________________________________________________________________________|___________

TSStatisticsManager::TSStatisticsManager(): 
  fModels		(NULL),
  fWorkspaces	(NULL),
  fResults	(NULL),
  fDefaultSampleFolder(NULL),
  fFileCompression(1)
{
  this->reset();
}


//__________________________________________________________________________________|___________

void TSStatisticsManager::info(TString message) {
  cout << "SFramework/TSStatisticsManager: " << message.Data() << endl;
}


//__________________________________________________________________________________|___________

void TSStatisticsManager::error(TString message) {
  info(TQStringUtils::makeBoldRed(TString("ERROR: ") + message));
}


//__________________________________________________________________________________|___________

void TSStatisticsManager::warn(TString message) {
  info(TQStringUtils::makeBoldYellow(TString("WARNING: ") + message));
}


//__________________________________________________________________________________|___________

void TSStatisticsManager::reset() {

  if (fModels) {
    delete fModels;
  }
  fModels = new TQFolder("models");
  
  if (fWorkspaces) {
    delete fWorkspaces;
  }
  fWorkspaces = new TQFolder("workspaces");
  
  
  if (fResults) {
    delete fResults;
  }
  fResults = new TQFolder("results");
}


//__________________________________________________________________________________|___________

void TSStatisticsManager::setDefaultSampleFolder(TQSampleFolder * sampleFolder) {

  fDefaultSampleFolder = sampleFolder;
}


//__________________________________________________________________________________|___________

TQSampleFolder * TSStatisticsManager::getDefaultSampleFolder() {

  return fDefaultSampleFolder;
}


//__________________________________________________________________________________|___________

TQFolder * TSStatisticsManager::getModels() {
  // Returns the list of models
  return fModels;
}


//__________________________________________________________________________________|___________

TQFolder * TSStatisticsManager::getWorkspaces() {
  // Returns the list of workspaces
  return fWorkspaces;
}


//__________________________________________________________________________________|___________

TQFolder * TSStatisticsManager::getResults() {
  // Returns the list of results
  return fResults;
}

//__________________________________________________________________________________|___________

Bool_t TSStatisticsManager::run(TQFolder * config) {
  bool dummy = config->getTagBoolDefault("dummy",false);
  std::vector<TString> libraries = config->getTagVString("extraLibs");
  for(size_t i=0; i<libraries.size(); ++i){
    TString lib(libraries[i]);
    TQStringUtils::ensureLeadingText(lib,"lib");
    if(!gSystem->Load(lib)){
      this->info(TString::Format("loaded external library '%s'",lib.Data()));
    } else {
      this->error(TString::Format("error loading external library '%s'",lib.Data()));
    }
  }
  TString outfile;
  if(config->getTagString("saveConfig",outfile)){
    if(outfile.Contains("$")){
      this->error("invalid output file given for saveConfig option: "+outfile);
      return false;
    }
    // TString outPath = TQPathManager::getPathManager()->getLocalPath(outfile);
    TString outPath = TQPathManager::getPathManager()->getTargetPath(outfile);
    TQUtils::ensureDirectoryForFile(outPath);
    TString resolved = TQPathManager::getPathManager()->getTargetPath(outPath);
    INFOclass("writing expanded config to '%s'",resolved.Data());
    if(resolved.EndsWith(".root")){
      config->writeToFile(resolved);
    } else {
      config->exportToTextFile(resolved);
    }
  }
  bool ok = true;
  TQFolderIterator itr(config->getListOfFolders("?"));
  while(itr.hasNext()){
    TQFolder* f = itr.readNext();
    f->detachFromBase(); //safety measure to prevent actions from changing configs for other actions
    if(!f) continue;
    TString name(f->GetName());
    TString action;
    TQStringUtils::readUpTo(name,action,".");
    TQStringUtils::removeLeading(name,".");
    f->setTagString(".label",name);
    auto it = Actions().find(action.Data());
    if(it == Actions().end()){
      ERRORclass("unknown action '%s'",f->GetName());
    } else {
      INFOclass(" === %s: %s === ",it->first.c_str(),f->GetName());
      //      this->fModels->print();
      //      this->fWorkspaces->print();
      //      this->fResults->print();
      if (!dummy){
        if(it->second->perform(f,this) > 0){
          ok = false;
        }
      }
    }
  }
  
  return ok;
}

//__________________________________________________________________________________|___________

void  TSStatisticsManager::setHistogramsFileCompression(Int_t compression){
  this->fFileCompression = compression;
}

//__________________________________________________________________________________|___________

Int_t TSStatisticsManager::getHistogramsFileCompression(){
  return this->fFileCompression;
}

//__________________________________________________________________________________|___________

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