#ifndef __TQ_GRIDSCANBOUND__
#define __TQ_GRIDSCANBOUND__

// TODO: remove this once full C++11 is used
#include <climits>
#include <iostream>
#include <vector>

#include <TObject.h>

// This class holds a single bound range, which means the range of values scanned over as an upper
// or lower or split cut. It can be a fixed value, a switch value, or a range with arbitrary step
// size.
class TQGridScanBound : public TObject {
public:
  // lower bin, upper bin, step size
  //using Range = std::array<int, 3>;
  // std::array doesn't have a streamer definition, apparently...
  using Range = std::vector<int>;
  enum class Direction { lower, upper, split };
  enum Type { normal = 0, split = 1 };

  // TODO: replace with numeric_limits once full C++11 is used
  //enum BinExtrema { min = 0, max = std::numeric_limits<int>::max };
  // Note: 0th bin includes underflow!
  enum BinExtrema { min = 0, max = INT_MAX/2 };

  TQGridScanBound() = default;
  TQGridScanBound(int fixedBin) :
  m_bins({fixedBin, fixedBin, 1})
  {}
  TQGridScanBound(int switchCutBin, int extremumBin) {
    range(switchCutBin, extremumBin);
  }
  TQGridScanBound(Range boundRange) :
    m_bins(boundRange)
  {}
  TQGridScanBound(int lowerBin, int upperBin, int stepSize) :
    m_bins(Range{lowerBin, upperBin, stepSize})
  {}

  void range(int fixedBin) {
    m_bins = (Range{fixedBin, fixedBin, 1});
  }
  int nPoints() const {
    return 1 + (m_bins[1] - m_bins[0]) / m_bins[2];
  }
  // Switch cut works by setting two scan points: one at the switch cut
  // val and the other at (including) the over- or underflow bin.
  void range(int switchCutBin, int extremumBin) {
    if (extremumBin > switchCutBin) {
      m_bins = (Range{switchCutBin, extremumBin, extremumBin - switchCutBin});
    } else {
      m_bins = (Range{0, switchCutBin, switchCutBin});
    }
  }
  void range(Range boundRange) {
    m_bins = boundRange;
  }

  bool isFixed() const {
    return m_bins[0] == m_bins[1];
  }

  Range* range() { return &m_bins; }
  Range range() const { return m_bins; }

  ClassDefOverride(TQGridScanBound, 1)
private:
  Range m_bins;
};

class TQGridScanBounds : public TObject {
public:
  using BinExtrema = TQGridScanBound::BinExtrema;
  TQGridScanBounds() :
      TQGridScanBounds(
        TQGridScanBound{BinExtrema::min, BinExtrema::min, 1},
        TQGridScanBound{BinExtrema::max, BinExtrema::max, 1}
      )
  {}
  TQGridScanBounds(TQGridScanBound lower, TQGridScanBound upper) : m_lower(lower), m_upper(upper) {}

  TQGridScanBound* lower() { return &m_lower; }
  TQGridScanBound lower() const { return m_lower; }
  TQGridScanBound* upper() { return &m_upper; }
  TQGridScanBound upper() const { return m_upper; }

private:
  TQGridScanBound m_lower;
  TQGridScanBound m_upper;

  ClassDefOverride(TQGridScanBounds, 1)
};

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