#ifndef __TQ_GRIDSCANRESULTS__
#define __TQ_GRIDSCANRESULTS__

#include <iostream>
#include <vector>
#include <utility>

#include "TLine.h"
#include "TString.h"
#include "TNamed.h"
#include "TGraphAsymmErrors.h"

#include "QFramework/TQGridScanPoint.h"
#include "QFramework/TQGridScanBound.h"
#include "QFramework/TQTaggable.h"
#include "QFramework/TQGridScanObservable.h"

class TQGridScanResults : public TQTaggable, public TNamed {
public:
  using NormalBins = std::vector<std::pair<int, int>>;
  using SplitBins = std::vector<int>;
  using ViewRanges = NormalBins;
  using BoundDirection = TQGridScanBound::Direction;
  struct InputHists{TString regionName; std::vector<TH1F> hists;};
  
  TQGridScanResults() :
    TNamed("TQGridScanResults", "TQGridScanResults")
  {}
  // TNamed doesn't have a constructor for a moved TString
  TQGridScanResults(const TString& name) :
    TNamed(name.Data(), "TQGridScanResults")
  {}
  ~TQGridScanResults () {
    for (auto obs : m_normalObs) {
      delete obs;
      obs = NULL;
    }
    for (auto obs : m_splitObs) {
      delete obs;
      obs = NULL;
    }
    m_normalObs.clear();
    m_splitObs.clear();
  }

  std::vector<TString> FOMDefinitions;
  
  // Sorts the points by descending significance
  void sortPoints();
  void sortPoints(unsigned int fom_index_for_sorting);

  //void printPoint(size_t n = 0);
  void printPoint(TQGridScanPoint* point);
  void printPoints(size_t first, size_t last);
  void printPoints(size_t last = -1);
  std::unique_ptr<TLine> drawCutLine(TH1* hist);
  
  void plotAndSaveAllSignificanceProfiles(double topFraction, const TString& options, TString outPath = "");
  void plotAndSaveAllSignificanceProfiles(int topNumber, const TString& options, TString outPath = "");
  void plotAndSaveSignificanceProfile(BoundDirection direction, int i, int topNumber, const TString& options, TString outPath = "");
  std::unique_ptr<TH1F> getSignificanceProfile(BoundDirection direction, int i, int topNumber);
  std::unique_ptr<TGraphAsymmErrors> makeGraphFromLowBinEdges(TH1* hist, BoundDirection direction);
  void setFOMIndexForPlotting(int fom_index_for_plotting);

  void plotInputDistributions(TQTaggable& tags, const TString& channel = "");
  
  std::vector<TQGridScanPoint>* points() { return &m_points; }
  const std::vector<TQGridScanPoint>& points() const { return m_points; }
  std::vector<TQGridScanNormalObservable*>* normalObs() { return &m_normalObs; }
  std::vector<TQGridScanSplitObservable*>* splitObs() { return &m_splitObs; }

  std::vector<InputHists>* inputHistsSig() { return &m_inputHistsSig; }
  std::vector<InputHists>* inputHistsBkg() { return &m_inputHistsBkg; }
  
protected:
  void init();
  bool isAcceptedPoint(const TQGridScanPoint& point);

  std::vector<TQGridScanPoint> m_points;

  // These store the arguments to make histograms for the respective quantities stored in gridscan points
  std::vector<TQGridScanNormalObservable*> m_normalObs;
  std::vector<TQGridScanSplitObservable*> m_splitObs;

  std::vector<InputHists> m_inputHistsSig; 
  std::vector<InputHists> m_inputHistsBkg; 
  
  bool m_sorted = false;
  
  int m_fom_index_for_plotting = 0;

  // No idea what this does
  ClassDefOverride(TQGridScanResults, 3)
};

#endif

 TQGridScanResults.h:1
 TQGridScanResults.h:2
 TQGridScanResults.h:3
 TQGridScanResults.h:4
 TQGridScanResults.h:5
 TQGridScanResults.h:6
 TQGridScanResults.h:7
 TQGridScanResults.h:8
 TQGridScanResults.h:9
 TQGridScanResults.h:10
 TQGridScanResults.h:11
 TQGridScanResults.h:12
 TQGridScanResults.h:13
 TQGridScanResults.h:14
 TQGridScanResults.h:15
 TQGridScanResults.h:16
 TQGridScanResults.h:17
 TQGridScanResults.h:18
 TQGridScanResults.h:19
 TQGridScanResults.h:20
 TQGridScanResults.h:21
 TQGridScanResults.h:22
 TQGridScanResults.h:23
 TQGridScanResults.h:24
 TQGridScanResults.h:25
 TQGridScanResults.h:26
 TQGridScanResults.h:27
 TQGridScanResults.h:28
 TQGridScanResults.h:29
 TQGridScanResults.h:30
 TQGridScanResults.h:31
 TQGridScanResults.h:32
 TQGridScanResults.h:33
 TQGridScanResults.h:34
 TQGridScanResults.h:35
 TQGridScanResults.h:36
 TQGridScanResults.h:37
 TQGridScanResults.h:38
 TQGridScanResults.h:39
 TQGridScanResults.h:40
 TQGridScanResults.h:41
 TQGridScanResults.h:42
 TQGridScanResults.h:43
 TQGridScanResults.h:44
 TQGridScanResults.h:45
 TQGridScanResults.h:46
 TQGridScanResults.h:47
 TQGridScanResults.h:48
 TQGridScanResults.h:49
 TQGridScanResults.h:50
 TQGridScanResults.h:51
 TQGridScanResults.h:52
 TQGridScanResults.h:53
 TQGridScanResults.h:54
 TQGridScanResults.h:55
 TQGridScanResults.h:56
 TQGridScanResults.h:57
 TQGridScanResults.h:58
 TQGridScanResults.h:59
 TQGridScanResults.h:60
 TQGridScanResults.h:61
 TQGridScanResults.h:62
 TQGridScanResults.h:63
 TQGridScanResults.h:64
 TQGridScanResults.h:65
 TQGridScanResults.h:66
 TQGridScanResults.h:67
 TQGridScanResults.h:68
 TQGridScanResults.h:69
 TQGridScanResults.h:70
 TQGridScanResults.h:71
 TQGridScanResults.h:72
 TQGridScanResults.h:73
 TQGridScanResults.h:74
 TQGridScanResults.h:75
 TQGridScanResults.h:76
 TQGridScanResults.h:77
 TQGridScanResults.h:78
 TQGridScanResults.h:79
 TQGridScanResults.h:80
 TQGridScanResults.h:81
 TQGridScanResults.h:82
 TQGridScanResults.h:83
 TQGridScanResults.h:84
 TQGridScanResults.h:85
 TQGridScanResults.h:86
 TQGridScanResults.h:87
 TQGridScanResults.h:88
 TQGridScanResults.h:89
 TQGridScanResults.h:90
 TQGridScanResults.h:91
 TQGridScanResults.h:92
 TQGridScanResults.h:93
 TQGridScanResults.h:94
 TQGridScanResults.h:95
 TQGridScanResults.h:96
 TQGridScanResults.h:97