#include "boost/optional.hpp"
#include "QFramework/TQGridScanPoint.h"
#include "QFramework/TQGridScanObservable.h"
#include "QFramework/TQHistogramUtils.h"
#include "QFramework/TQLibrary.h"
#include <iostream>

////////////////////////////////////////////////////////////////////////////////////////////////
//
// TQGridScanPoint
//
// a single point in configuration space
// can be manipulated by any TQSignificanceEvaluator 
// to store all necessary information for later investigation
//
////////////////////////////////////////////////////////////////////////////////////////////////

using std::vector;
using std::pair;
using boost::optional;

using NormalBounds = TQGridScanPoint::NormalBounds;
using SplitBounds = TQGridScanPoint::SplitBounds;
using NormalVals = TQGridScanPoint::NormalVals;
using SplitVals = TQGridScanPoint::SplitVals;
//using NormalObsVec = TQGridScanPoint::NormalObsVec;
//using SplitObsVec = TQGridScanPoint::SplitObsVec;

ClassImp(TQGridScanPoint)

//TQGridScanPoint::NormalObsVec* TQGridScanPoint::normalObs = nullptr;
//TQGridScanPoint::SplitObsVec* TQGridScanPoint::splitObs = nullptr;

TQGridScanPoint::TQGridScanPoint(
    NormalBounds normalBounds,
    SplitBounds splitBounds,
    double significance,
    TString info
) :
  m_significance(significance),
  m_info(info),
  m_normalBounds(normalBounds),
  m_splitBounds(splitBounds)
{}

TQGridScanPoint::TQGridScanPoint(
    NormalBounds normalBounds,
    double significance,
    TString info
) :
  m_significance(significance),
  m_info(info),
  m_normalBounds(normalBounds)
{}
TQGridScanPoint::TQGridScanPoint(
    NormalBounds normalBounds,
    SplitBounds splitBounds,
    std::vector<double> foms,
    TString info
) :
  m_significance(foms[0]), // for sorting the first FOM is used!
  m_foms(foms),
  m_info(info),
  m_normalBounds(normalBounds),
  m_splitBounds(splitBounds)
{}
TQGridScanPoint::TQGridScanPoint(
    NormalBounds normalBounds,
    std::vector<double> foms,
    TString info
) :
  m_significance(foms[0]), // for sorting the first FOM is used!
  m_foms(foms),
  m_info(info),
  m_normalBounds(normalBounds)
{}

const NormalVals& TQGridScanPoint::normalVals(const vector<TQGridScanNormalObservable*>& obsVec) {
  if (m_normalVals.empty()) {
    for (size_t i = 0; i < m_normalBounds.size(); ++i) {
      auto lowerBound = m_normalBounds[i].first;
      auto upperBound = m_normalBounds[i].second;
      double lowerVal = kValNotSet;
      double upperVal = kValNotSet;
      auto obs = obsVec[i];
      lowerVal = obs->axis()->GetBinLowEdge(lowerBound);
      upperVal = obs->axis()->GetBinUpEdge(upperBound);
      m_normalVals.push_back(std::make_pair(lowerVal, upperVal));
    }
  }
  return m_normalVals;
}

const SplitVals& TQGridScanPoint::splitVals(const vector<TQGridScanSplitObservable*>& obsVec) {
  if (m_splitVals.empty()) {
    for (size_t i = 0; i < m_splitBounds.size(); ++i) {
      auto bound = m_splitBounds[i];
      auto obs = obsVec[i];
      auto binEdge = obs->axis()->GetBinLowEdge(bound);
      m_splitVals.push_back(binEdge);
    }
  }
  return m_splitVals;
}

#if 0
void TQGridScanPoint::clear() {
  // delete all information on this point
  variables.clear();
  this->significance = 0;
  this->id = 0;
  coordinates.clear();
  switchStatus.clear();
}

TQGridScanPoint::~TQGridScanPoint() {
  // standard destructor
  this->clear();
}
#endif
 TQGridScanPoint.cxx:1
 TQGridScanPoint.cxx:2
 TQGridScanPoint.cxx:3
 TQGridScanPoint.cxx:4
 TQGridScanPoint.cxx:5
 TQGridScanPoint.cxx:6
 TQGridScanPoint.cxx:7
 TQGridScanPoint.cxx:8
 TQGridScanPoint.cxx:9
 TQGridScanPoint.cxx:10
 TQGridScanPoint.cxx:11
 TQGridScanPoint.cxx:12
 TQGridScanPoint.cxx:13
 TQGridScanPoint.cxx:14
 TQGridScanPoint.cxx:15
 TQGridScanPoint.cxx:16
 TQGridScanPoint.cxx:17
 TQGridScanPoint.cxx:18
 TQGridScanPoint.cxx:19
 TQGridScanPoint.cxx:20
 TQGridScanPoint.cxx:21
 TQGridScanPoint.cxx:22
 TQGridScanPoint.cxx:23
 TQGridScanPoint.cxx:24
 TQGridScanPoint.cxx:25
 TQGridScanPoint.cxx:26
 TQGridScanPoint.cxx:27
 TQGridScanPoint.cxx:28
 TQGridScanPoint.cxx:29
 TQGridScanPoint.cxx:30
 TQGridScanPoint.cxx:31
 TQGridScanPoint.cxx:32
 TQGridScanPoint.cxx:33
 TQGridScanPoint.cxx:34
 TQGridScanPoint.cxx:35
 TQGridScanPoint.cxx:36
 TQGridScanPoint.cxx:37
 TQGridScanPoint.cxx:38
 TQGridScanPoint.cxx:39
 TQGridScanPoint.cxx:40
 TQGridScanPoint.cxx:41
 TQGridScanPoint.cxx:42
 TQGridScanPoint.cxx:43
 TQGridScanPoint.cxx:44
 TQGridScanPoint.cxx:45
 TQGridScanPoint.cxx:46
 TQGridScanPoint.cxx:47
 TQGridScanPoint.cxx:48
 TQGridScanPoint.cxx:49
 TQGridScanPoint.cxx:50
 TQGridScanPoint.cxx:51
 TQGridScanPoint.cxx:52
 TQGridScanPoint.cxx:53
 TQGridScanPoint.cxx:54
 TQGridScanPoint.cxx:55
 TQGridScanPoint.cxx:56
 TQGridScanPoint.cxx:57
 TQGridScanPoint.cxx:58
 TQGridScanPoint.cxx:59
 TQGridScanPoint.cxx:60
 TQGridScanPoint.cxx:61
 TQGridScanPoint.cxx:62
 TQGridScanPoint.cxx:63
 TQGridScanPoint.cxx:64
 TQGridScanPoint.cxx:65
 TQGridScanPoint.cxx:66
 TQGridScanPoint.cxx:67
 TQGridScanPoint.cxx:68
 TQGridScanPoint.cxx:69
 TQGridScanPoint.cxx:70
 TQGridScanPoint.cxx:71
 TQGridScanPoint.cxx:72
 TQGridScanPoint.cxx:73
 TQGridScanPoint.cxx:74
 TQGridScanPoint.cxx:75
 TQGridScanPoint.cxx:76
 TQGridScanPoint.cxx:77
 TQGridScanPoint.cxx:78
 TQGridScanPoint.cxx:79
 TQGridScanPoint.cxx:80
 TQGridScanPoint.cxx:81
 TQGridScanPoint.cxx:82
 TQGridScanPoint.cxx:83
 TQGridScanPoint.cxx:84
 TQGridScanPoint.cxx:85
 TQGridScanPoint.cxx:86
 TQGridScanPoint.cxx:87
 TQGridScanPoint.cxx:88
 TQGridScanPoint.cxx:89
 TQGridScanPoint.cxx:90
 TQGridScanPoint.cxx:91
 TQGridScanPoint.cxx:92
 TQGridScanPoint.cxx:93
 TQGridScanPoint.cxx:94
 TQGridScanPoint.cxx:95
 TQGridScanPoint.cxx:96
 TQGridScanPoint.cxx:97
 TQGridScanPoint.cxx:98
 TQGridScanPoint.cxx:99
 TQGridScanPoint.cxx:100
 TQGridScanPoint.cxx:101
 TQGridScanPoint.cxx:102
 TQGridScanPoint.cxx:103
 TQGridScanPoint.cxx:104
 TQGridScanPoint.cxx:105
 TQGridScanPoint.cxx:106
 TQGridScanPoint.cxx:107
 TQGridScanPoint.cxx:108
 TQGridScanPoint.cxx:109
 TQGridScanPoint.cxx:110
 TQGridScanPoint.cxx:111
 TQGridScanPoint.cxx:112
 TQGridScanPoint.cxx:113
 TQGridScanPoint.cxx:114
 TQGridScanPoint.cxx:115
 TQGridScanPoint.cxx:116
 TQGridScanPoint.cxx:117
 TQGridScanPoint.cxx:118
 TQGridScanPoint.cxx:119
 TQGridScanPoint.cxx:120