#include <cmath>

#include <QDebug>
#include <QFile>

#if 0
// For debugging purposes.
#include <QFile>
#endif

#include "../../types.h"
#include "massspectrumcombiner.h"

namespace pappso
{


//! Construct an uninitialized instance.
MassSpectrumCombiner::MassSpectrumCombiner(QObject *parent_p): QObject(parent_p)
{
}

MassSpectrumCombiner::MassSpectrumCombiner(int decimal_places,
                                           QObject *parent_p)
  : QObject(parent_p), MassDataCombinerInterface(decimal_places)
{
}

MassSpectrumCombiner::MassSpectrumCombiner(std::vector<pappso_double> bins,
                                           int decimalPlaces,
                                           QObject *parent_p)
  : QObject(parent_p), MassDataCombinerInterface(decimalPlaces)
{
  m_bins.assign(bins.begin(), bins.end());
}

MassSpectrumCombiner::MassSpectrumCombiner(const MassSpectrumCombiner &other,
                                           QObject *parent_p)
  : QObject(parent_p), MassDataCombinerInterface(other.m_decimalPlaces)
{
  m_bins.assign(other.m_bins.begin(), other.m_bins.end());

  // QString debug_string = QString(
  //"Number of bins: %1\n"
  //"First bins: %2 %3 %4 -- Last bins: %5 %6 %7\n")
  //.arg(m_bins.size())
  //.arg(m_bins[0], 0, 'f', 6)
  //.arg(m_bins[1], 0, 'f', 6)
  //.arg(m_bins[2], 0, 'f', 6)
  //.arg(m_bins[m_bins.size() - 3], 0, 'f', 6)
  //.arg(m_bins[m_bins.size() - 2], 0, 'f', 6)
  //.arg(m_bins[m_bins.size() - 1], 0, 'f', 6);

  // qDebug().noquote() << debug_string;
}

MassSpectrumCombiner::MassSpectrumCombiner(MassSpectrumCombinerCstSPtr other,
                                           QObject *parent_p)
  : QObject(parent_p), MassDataCombinerInterface(other->m_decimalPlaces)
{
  m_bins.assign(other->m_bins.begin(), other->m_bins.end());
}

//! Destruct the instance.
MassSpectrumCombiner::~MassSpectrumCombiner()
{
  m_bins.clear();
}

void
MassSpectrumCombiner::setBins(std::vector<pappso_double> bins)
{
  m_bins.assign(bins.begin(), bins.end());

  // QString debug_string = QString(
  //"Number of bins: %1\n"
  //"First bins: %2 %3 %4 -- Last bins: %5 %6 %7\n")
  //.arg(m_bins.size())
  //.arg(m_bins[0], 0, 'f', 6)
  //.arg(m_bins[1], 0, 'f', 6)
  //.arg(m_bins[2], 0, 'f', 6)
  //.arg(m_bins[m_bins.size() - 3], 0, 'f', 6)
  //.arg(m_bins[m_bins.size() - 2], 0, 'f', 6)
  //.arg(m_bins[m_bins.size() - 1], 0, 'f', 6);

  // qDebug().noquote() << debug_string;

  emit binCountChanged();
}

const std::vector<pappso_double> &
MassSpectrumCombiner::getBins() const
{
  return m_bins;
}

std::size_t
MassSpectrumCombiner::binCount() const
{
  return m_bins.size();
}

//! Find the bin that will contain \p mz.
std::vector<pappso_double>::iterator
MassSpectrumCombiner::findBin(pappso_double mz)
{
  return std::find_if(m_bins.begin(), m_bins.end(), [mz](pappso_double bin) {
    return (mz <= bin);
  });
}

QString
MassSpectrumCombiner::binsAsString() const
{
  QString text;

  for(auto &bin : m_bins)
    text += QString("%1\n").arg(bin, 0, 'f', 6);

  text += "\n";

  return text;
}

void
MassSpectrumCombiner::registerJsConstructor(QJSEngine *engine)
{
  // qDebug() << "registerJsConstructor for MassSpectrumCombiner to QJSEngine.";

  if(engine == nullptr)
    {
      qFatal() << "Cannot register class: engine is null";
    }

  // Register the meta object as a constructor
  QJSValue jsMetaObject =
    engine->newQMetaObject(&MassSpectrumCombiner::staticMetaObject);
  engine->globalObject().setProperty("MassSpectrumCombiner", jsMetaObject);
}

} // namespace pappso
