#include "QFramework/TQUniqueCut.h"
#include "QFramework/TQStringUtils.h"
#include <algorithm>

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

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQUniqueCut:
//
// This class is a special version of the TQCompiledCut.
// The intention of this class is to provide functionality to remove
// overlap between a set of samples.
// 
// This cut is most sensibly used as the root of a hierarchy of TQCompiledCuts.
// As such, it will take care that every event will only be considered once.
// All RunNumbers and EventNumbers are stored and compared with to achieve this,
// any events recognized as duplicates will be rejected.
// Please note that this procedure is very demanding in terms of CPU and RAM,
// and might easily lead to severe problems when analysing large sample sets.
//
// In such cases, please consider removing the overlap on nTuple code level.
// 
////////////////////////////////////////////////////////////////////////////////////////////////

bool TQUniqueCut::printOnVeto = false;

ClassImp(TQUniqueCut)

// this is necessary because std::is_sorted is defined in c++11
// in order for this code to compile with older compilers as well,
// this function needs to be provided
#if __cplusplus >= 201103L
#define IS_SORTED(first,last) std::is_sorted(first,last)
#else 
template<class ForwardIt>
bool is_sorted(ForwardIt first, ForwardIt last){
  if (first != last) {
    ForwardIt next = first;
    while (++next != last) {
      if (*next < *first)
        return ( next == last );
      first = next;
    }
  }
  return true;
}
#define IS_SORTED(first,last) is_sorted(first,last);
#endif

bool TQUniqueCut::isMergeable() const {
  // returns false, since TQUniqueCuts are never mergeable
  return false;
}

bool TQUniqueCut::setBranchNames(const TString& runBranch, const TString& evtBranch){
  // set the branch names used for run number and event number
  this->eventNumberBranch = evtBranch;
  this->runNumberBranch = runBranch;
  return true;
}

void TQUniqueCut::initUniqueCut(){
  // initialize this instance of TQUniqueCut
  this->SetName("UniqueCut");
  this->enabled = true;
}

TQUniqueCut::TQUniqueCut() :
  runNumberBranch("run"),
  eventNumberBranch("event")
{
  // default constructor of the TQUniqueCut
  this->initUniqueCut();
}

TQUniqueCut::TQUniqueCut(const TString& name) :
  runNumberBranch("run"),
  eventNumberBranch("event")
{
  // default constructor of the TQUniqueCut
  this->initUniqueCut();
  this->SetName(name);
}

TQUniqueCut::TQUniqueCut(const TString& runBranch, const TString& evtBranch) :
  runNumberBranch(runBranch),
  eventNumberBranch(evtBranch)
{
  // constructor of the TQUniqueCut class, taking branch names for run and event number
  this->initUniqueCut();
}

TQUniqueCut::TQUniqueCut(const TString& name, const TString& runBranch, const TString& evtBranch) :
  runNumberBranch(runBranch),
  eventNumberBranch(evtBranch)
{
  // constructor of the TQUniqueCut class, taking a name as well as branch names for run and event number
  this->initUniqueCut();
  this->SetName(name);
}

const TString& TQUniqueCut::getRunNumberExpression() const {
  return this->runNumberBranch;
}

const TString& TQUniqueCut::getEventNumberExpression() const {
  return this->eventNumberBranch;
}

void TQUniqueCut::clear(){
  // clear all saved information
  this->runNumbers.clear();
  this->eventNumbers.clear();
}

void TQUniqueCut::setActive(bool active){
  // activate/deactivate this instance
  this->enabled = active;
}

TObjArray* TQUniqueCut::getOwnBranches(){
  // add the branches required by this instance of TQUniqueCut to the internal list of branches
  TObjArray* bNames = new TObjArray();
  TObjArray* rnb = this->runNumberObservable ? this->runNumberObservable->getBranchNames() : nullptr;
  TObjArray* enb = this->eventNumberObservable ? this->eventNumberObservable->getBranchNames() : nullptr;
  
  if(rnb){
        bNames -> AddAll(rnb);
        rnb->SetOwner(false);
        delete rnb;
  }
  
  if(enb){
        bNames -> AddAll(enb);
        enb->SetOwner(false);
        delete enb;
  }
  //bNames->Add(new TObjString(this->runNumberBranch));
  //bNames->Add(new TObjString(this->eventNumberBranch));
  return bNames;
}


bool TQUniqueCut::checkUnique(std::set<long>& entries, long newEntry){
  // check if an entry is new to a set
  // if so, add it at the appropriate place and return true
  // else return false
  DEBUGclass("entering function");
  if (entries.count(newEntry)) return false;
  entries.insert(newEntry);
  return true;
}

long TQUniqueCut::getIndex(std::vector<long>& entries, long entry){
  // retrieve the index of an entry in a sorted vector
  // if the entry is not in the vector yet, add it appropriately
  // return the index of the element
  DEBUGclass("attempting to find index of %d",entry);
  if(entries.size() < 1){
    DEBUGclass("adding %d as first entry",entry);
    entries.insert(entries.begin(),entry);
    return 0;
  }
  long idx = entries.size() -1;
  DEBUGclass("checking entry %d against %d",entry,entries[idx]);
  if(entry > entries[idx]){
    DEBUGclass("adding entry %d at %d",entry,idx);
    entries.push_back(entry);
    return idx+1;
  }
  DEBUGclass("searching for entry %d",entry);
  while(idx >= 0 && entry < entries[idx]){
    idx--;
  }
  DEBUGclass("stopping search at index %d",idx);
  if(idx < 0 || entry > entries[idx]){
    long newidx = 1+idx;
    DEBUGclass("did not find entry %d, inserting  at %d",entry,newidx);
    entries.insert(entries.begin()+newidx,entry);
    return newidx;
  }
  DEBUGclass("found %d==%d at %d",entry,entries[idx],idx);
  return idx;
}


bool TQUniqueCut::passed(bool doPrint) const {
  // checks the run and event numbers of the current event
  // returns true if they are unique, false if this combination 
  // has already been encountered before
  if(!this->enabled) {
    if (doPrint) {
      INFOclass("[TreeIndex: %ld] UniqueCut '%s' passed (cut not enabled)", this->fTree?this->fTree->GetReadEntry():-1, this->GetName());
    }
    return true;
  }
  long event = this->eventNumberObservable->getValue();
  long run = this->runNumberObservable->getValue();
  
  DEBUGclass("checking unique event %ld : %ld",run,event);
  
  long runIdx = getIndex(runNumbers,run);
  if(runNumbers.size() > eventNumbers.size()){
    DEBUGclass("extending eventnumber list");
    auto b = eventNumbers.begin();
    std::set<long> newelem;
    eventNumbers.insert(b+runIdx,newelem);
  }
  #ifdef _DEBUG_
  if(runIdx >= (long)(eventNumbers.size())){
    throw std::runtime_error("event number list has insufficient length!");
  } else {
    DEBUGclass("event number list length %ld is suffucient for run index %ld",(long)(eventNumbers.size()),runIdx);
  }
  #endif
  
  DEBUGclass("checking unique for run %ld at %ld (%ld events)",runNumbers[runIdx],runIdx,eventNumbers[runIdx].size());
  const bool unique = TQUniqueCut::checkUnique(eventNumbers[runIdx],event);
  DEBUGclass("returning %d",unique);
  if(!unique){
    if (doPrint || TQUniqueCut::printOnVeto) {
      INFOclass("[TreeIndex: %ld] UniqueCut failed: event known: runNumber %ld : eventNumber %ld", this->fTree?this->fTree->GetReadEntry():-1, run, event);
    } else {
      DEBUGclass("[TreeIndex: %ld] UniqueCut failed: event known: runNumber %ld : eventNumber %ld", this->fTree?this->fTree->GetReadEntry():-1, run, event);
    }
    #ifdef _DEBUG_
    //this->printLists();
    #endif
  } else {
    if (doPrint) {
      INFOclass("[TreeIndex: %ld] UniqueCut passed: new event: runNumber %ld : eventNumber %ld",this->fTree?this->fTree->GetReadEntry():-1, run,event);
    } else {
      DEBUGclass("[TreeIndex: %ld] UniqueCut passed: new event: runNumber %ld : eventNumber %ld",this->fTree?this->fTree->GetReadEntry():-1, run,event);
    }
    
  }
  return unique;
}

bool TQUniqueCut::initializeObservables() {
  // initialize the observables required by this TQUniqueCut
  this->eventNumberObservable = TQObservable::getObservable(this->eventNumberBranch,this->fSample);
  this->runNumberObservable = TQObservable::getObservable(this->runNumberBranch,this->fSample);

  if (!runNumberObservable || !eventNumberObservable) return false;
  bool ok = true;
  if (!runNumberObservable ->initialize(this->fSample)) {
    ERRORclass("Failed to initialize runNumberObservable obtained from expression '%s' in TQUniqueCut '%s' for sample '%s'",this->runNumberBranch.Data(), this->GetName(), this->fSample->getPath().Data()); 
    ok = false;
  }
  
  if (!eventNumberObservable->initialize(this->fSample)){
    ok = false;
  }

  if (!ok) {
    this->finalizeObservables();
    return false;
  }
  return true;
}

bool TQUniqueCut::finalizeObservables() {
  // finalize the observables required by this TQUniqueCut
  if (runNumberObservable && eventNumberObservable){
    return runNumberObservable ->finalize() && eventNumberObservable ->finalize();
  }
  if(runNumberObservable) runNumberObservable ->finalize();
  if(eventNumberObservable) eventNumberObservable ->finalize();
  return false;
}


void TQUniqueCut::printLists() const {
  // print the internal lists of run and event numbers
  // WARNING: these lists can be excessively long!
  for (size_t i=0; i<runNumbers.size(); i++) {
    std::cout << "===" << runNumbers[i] << "===" << std::endl;
    size_t length = eventNumbers[i].size();
    for (const long& en : eventNumbers[i]) {
      if (--length) {
        std::cout << en << ", ";
      } else {
        std::cout<< en << std::endl; //last entry
      }
    }
  }
}

bool TQUniqueCut::initializeSelfSampleFolder(TQSampleFolder* sf){
  //@tag:[resetUniqueCut] If this boolean sample folder tag is set to true the run and event numbers of this cut are cleared upon initialization and finalization of the unique cut.
  if(sf->getTagBoolDefault("resetUniqueCut",false)) this->clear();
  return true;
}

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