#include "YODA/BinnedAxis.h"
#include "YODA/BinnedStorage.h"
#include "YODA/Dbn.h"
#include "YODA/Utils/Formatting.h"
#include "YODA/Utils/MathUtils.h"
#include "YODA/Utils/MetaUtils.h"
#include <array>
#include <cmath>
#include <iostream>

using namespace std;
using namespace YODA;


int main() {

  int rtn = EXIT_SUCCESS;

  #define TESTBS(bs, x, iref) \
    MSG(x << " => " << bs.index(x) << ": " << boolalpha << (bs.index(x) == iref)); \
    if (bs.index(x) != iref) rtn = EXIT_FAILURE;

  // const vector<double> linedges = linspace(3, 1, 101);
  // const vector<double> logedges = logspace(3, 1, 101);
  // YODA::BinnedAxis xaxis (linedges);
  // YODA::BinnedAxis yaxis (logedges);

  // std::vector< YODA:: BinnedAxis> ba;
  // ba.push_back(xaxis);
  // YODA::Binning<1> bn1d  (ba);

  // ba.push_back(yaxis);
  // YODA::Binning<2> bn2d  (ba);

  // std::tuple<int,char,double> t{43, 'a', 4.2};

  // std::size_t total = 0;
  // MetaUtils::staticFor(t, [&] (auto w) { total += int(w);});

  // std::cout << "Total test: " << total << std::endl;

  // constexpr auto N = 10;
  // auto testDbnFill = Dbn<N>();
  // Dbn<N>().fill(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
  // testDbnFill.fill(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0);
  // testDbnFill.fill(2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0);
  // assert(fuzzyEquals(testDbnFill.getMean(1), 1.5));
  // std::cout << testDbnFill.toString() << '\n' << testDbnFill.getMean(1) << std::endl;

//  BinnedObject<1, 1, YODA::Dbn1D > hist1d (bn1d);
//  BinnedObject<1, 2, YODA::Dbn2D > prof1d (bn1d);
//  BinnedObject<2, 2, YODA::Dbn2D > hist2d (bn2d);
//
//  hist1d.fill({3},0.1);
//  hist1d.fill({33},0.3);
//  hist1d.fill({38},2.3);
//  hist1d.fill({83},0.2);
//
//  /*prof1d.fill({3,200},0.1);
//  prof1d.fill({33,2},0.3);
//  prof1d.fill({38,53},2.3);
//  prof1d.fill({83,23},0.2);*/
//
//  hist2d.fill({3,200},0.1);
//  hist2d.fill({33,2},0.3);
//  hist2d.fill({38,53},2.3);
//  hist2d.fill({83,23},0.2);
//
//  for ( int iBin =0 ; iBin < hist1d.numBins() ; ++iBin){
//    std::cout << "Hist1D contents of bin " << iBin<< " are " << hist1d.getBinContents()[iBin].toString() << std::endl;
//  }
//
//  std::cout << std::endl;
//  for ( int iBin =0 ; iBin < prof1d.numBins() ; ++iBin){
//    std::cout << "Prof1D contents of bin " << iBin<< " are " << prof1d.getBinContents()[iBin].toString() << std::endl;
//  }
//
//  std::cout << std::endl;
//  for ( int iBin =0 ; iBin < hist2d.numBins() ; ++iBin){
//    std::cout << "Hist2D contents of bin " << iBin<< " are " << hist2d.getBinContents()[iBin].toString() << std::endl;
//  }
//

  return rtn;
}
