/**
 * \file pappsomspp/massspectrum/massspectrum.h
 * \date 15/3/2015
 * \author Olivier Langella
 * \brief basic mass spectrum
 */

/*******************************************************************************
 * Copyright (c) 2015 Olivier Langella <Olivier.Langella@moulon.inra.fr>.
 *
 * This file is part of the PAPPSOms++ library.
 *
 *     PAPPSOms++ is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     PAPPSOms++ is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with PAPPSOms++.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@moulon.inra.fr> - initial API and
 *implementation
 ******************************************************************************/

#pragma once

#include <vector>
#include <memory>

#include <QDataStream>

#include "pappsomspp/export-import-config.h"

#include "pappsomspp/core/mzrange.h"
#include "pappsomspp/core/trace/trace.h"


namespace pappso
{

// Forward declaration.
class MassSpectrum;

PMSPP_LIB_DECL QDataStream &operator<<(QDataStream &out, const MassSpectrum &spectrum);
PMSPP_LIB_DECL QDataStream &operator>>(QDataStream &out, MassSpectrum &spectrum);

typedef std::shared_ptr<MassSpectrum> MassSpectrumSPtr;
typedef std::shared_ptr<const MassSpectrum> MassSpectrumCstSPtr;

class MassSpectrumCombinerInterface;


//! Class to represent a mass spectrum.
/*!
 * A mass spectrum is a collection of DataPoint instances. Moreover, it has
 * internal data that represent the context of the acquisition of the data:
 * retention time and drift time (if the experiment was an ion mobility mass
 * spectrometry experiment).
 *
 * A MassSpectrum cannot perform combinations. For combination of mass
 * spectra, the class to use is MassSpectrumCombinator.
 */
class PMSPP_LIB_DECL MassSpectrum : public Trace
{

  public:
  MassSpectrum();
  MassSpectrum(std::vector<std::pair<pappso_double, pappso_double>> &data_point_vector);
  MassSpectrum(std::vector<DataPoint> &data_point_vector);

  MassSpectrum(const MapTrace &other);
  MassSpectrum(const Trace &other);
  MassSpectrum(Trace &&other); // move constructor

  MassSpectrum(const MassSpectrum &other);
  MassSpectrum(MassSpectrum &&other); // move constructor

  virtual ~MassSpectrum();

  virtual MassSpectrum &operator=(const MassSpectrum &other);
  virtual MassSpectrum &operator=(MassSpectrum &&other);

  using Trace::operator=;

  MassSpectrumSPtr makeMassSpectrumSPtr() const;
  MassSpectrumCstSPtr makeMassSpectrumCstSPtr() const;

  /** @brief apply a filter on this MassSpectrum
   * @param filter to process the MassSpectrum
   * @return reference on the modified MassSpectrum
   */
  virtual MassSpectrum &massSpectrumFilter(const MassSpectrumFilterInterface &filter) final;

  pappso_double totalIonCurrent() const;
  // Alias for totalIonCurrent().
  pappso_double tic() const;
  pappso_double tic(double mzStart, double mzEnd);

  const DataPoint &maxIntensityDataPoint() const;

  const DataPoint &minIntensityDataPoint() const;

  void sortMz();

  bool equals(const MassSpectrum &other, PrecisionPtr precision) const;

  MassSpectrum filterSum(const MzRange &mass_range) const;


  // friend QDataStream& operator<<(QDataStream& out, const MassSpectrum&
  // massSpectrum);
  // friend QDataStream& operator>>(QDataStream& out, MassSpectrum&
  // massSpectrum);

  void debugPrintValues() const;
};


} // namespace pappso


Q_DECLARE_METATYPE(pappso::MassSpectrum);
Q_DECLARE_METATYPE(pappso::MassSpectrum *);

extern int massSpectrumMetaTypeId;
extern int massSpectrumPtrMetaTypeId;
