#include "YODA/Counter.h"
#include "YODA/Histo.h"
#include "YODA/Profile.h"
#include "YODA/BinnedEstimate.h"
#include "YODA/Scatter.h"
#include <cmath>
#include <vector>
#include <iostream>
#include <string>

using namespace std;
using namespace YODA;


int main() {

  Counter c1;
  Histo1D h1(20, 0.0, 1.0);
  for (size_t n = 0; n < 1000; ++n) {
    const double num = rand()/static_cast<double>(RAND_MAX);
    c1.fill();
    h1.fill(num);
  }

  Counter c2;
  c2.deserializeContent(c1.serializeContent());
  if (c1.lengthContent() != c2.lengthContent() || c1.sumW() != c2.sumW())  return CHECK_TEST_RES(false);

  Histo1D h2(20, 0.0, 1.0);
  h2.deserializeContent(h1.serializeContent());
  if (h1.lengthContent() != h2.lengthContent() || h1.integral() != h2.integral())  return CHECK_TEST_RES(false);

  Estimate0D e1 = c1.mkEstimate(), e2;
  e2.deserializeContent(e1.serializeContent());
  if (e1.lengthContent() != e2.lengthContent() || e1.val() != e2.val())  return CHECK_TEST_RES(false);

  Estimate1D b1 = h1.mkEstimate();
  Estimate1D b2 = b1.clone(); b2.reset();
  b2.deserializeContent(b1.serializeContent());
  if (b1.lengthContent() != b2.lengthContent() || b1.auc() != b2.auc())  return CHECK_TEST_RES(false);

  Scatter2D s1 = h1.mkScatter(), s2;
  s2.deserializeContent(s1.serializeContent());
  if (s1.lengthContent() != s2.lengthContent() || s1.numPoints() != s2.numPoints())  return CHECK_TEST_RES(false);

  // Test meta-serialisations
  h1.addAnnotation("foo", "bar");
  std::vector<std::string> annos = h1.serializeMeta();
  h2.deserializeMeta(annos);
  if (h1.lengthMeta() != h2.lengthMeta() || h2.annotation("foo") != "bar"s)  return CHECK_TEST_RES(false);

  h2.rmAnnotation("foo");
  annos.pop_back();
  bool pass = false;
  try {
    h2.deserializeMeta(annos);
  }
  catch (const UserError&) {
    pass = true;
  }
  if (!pass)  return CHECK_TEST_RES(false);

  return EXIT_SUCCESS;
}
