#pragma once

#include <vector>
#include <memory>

#include <QDataStream>

#include "../../exportinmportconfig.h"
#include "../../types.h"
#include "../../mzrange.h"

#include "../../massspectrum/massspectrum.h"
#include "../../trace/datapoint.h"
#include "../../trace/maptrace.h"
#include "../filters/filterresample.h"
#include "massdatacombinerinterface.h"


namespace pappso
{


class MassSpectrumCombiner;

typedef std::shared_ptr<const MassSpectrumCombiner> MassSpectrumCombinerCstSPtr;
typedef std::shared_ptr<MassSpectrumCombiner> MassSpectrumCombinerSPtr;


class PMSPP_LIB_DECL MassSpectrumCombiner : public MassDataCombinerInterface
{


  public:
  MassSpectrumCombiner();
  MassSpectrumCombiner(std::vector<pappso_double> bins, int decimalPlaces = -1);
  MassSpectrumCombiner(int decimal_places);
  MassSpectrumCombiner(MassSpectrumCombinerCstSPtr other);
  MassSpectrumCombiner(const MassSpectrumCombiner &other);
  MassSpectrumCombiner(const MassSpectrumCombiner &&other);

  virtual ~MassSpectrumCombiner();

  std::vector<pappso_double>::const_iterator begin() const;
  std::vector<pappso_double>::const_iterator end() const;
  std::vector<pappso_double>::iterator begin();
  std::vector<pappso_double>::iterator end();

  void setBins(std::vector<pappso_double> bins);
  const std::vector<pappso_double> &getBins() const;
  std::size_t binCount() const;

  virtual MapTrace &combine(MapTrace &map_trace, const Trace &trace) const;

  virtual MapTrace &combine(MapTrace &map_trace_out,
                            const MapTrace &map_trace_in) const;

  protected:
  std::vector<pappso_double> m_bins;

  std::vector<pappso_double>::iterator findBin(pappso_double mz);

  private:
  // This function combines trace into map_trace but does not handle the
  // situation where any filtering step was asked for. This function is called
  // by public combine function after filtering work has occurred already. This
  // function is the functional lowest common denominator for all the public
  // combine functions.
  virtual MapTrace &combineNoFilteringStep(MapTrace &map_trace,
                                           const Trace &trace) const = 0;
};


} // namespace pappso
