/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2018 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * This program 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.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */


#pragma once


/////////////////////// Qt includes
#include <QObject>
#include <QMap>


/////////////////////// Local includes
#include <libmass/DataPoint.hpp>


namespace msXpSlibmass
{


//! The Trace class provides a QList<DataPoint*> list.
/*!

  This class serves as a base class for the various traces that need to be
  dealt with in msXpertSuite\: mass spectra, drift spectra and TIC
  chromatograms, and in the scripting environment, all the graphical
  representations of these entities\: the graphs.

  The Trace class has all the methods required to add/subtract various Trace
  objects into a single Trace object (that is called combination when speaking
  of mass spectra, for example).

*/
class Trace : public QObject, public QList<DataPoint *>
{
  Q_OBJECT

  friend class TraceJs;

  protected:
  //! Title of the trace.
  QString m_title;

  //! Decimal places to use when working with keys (for mass spectra, for
  //! example)
  /*!

    Limiting the number of decimal places is useful in some occasions as a
    poor man's binning system. In particular, it is useful when creating the
    mz=f(dt) color map.

*/
  int m_decimalPlaces = -1;

  //! Index of the DataPoint instance that was last modified.
  /*!

    When performing lengthy operations, like mass spectrum combination, this
    value allows for a considerable speedup of the operations. Indeed, storing
    the last modified DataPoint instance allows for almost direct DataPoint
    addressing when performing the next combination (this is possible because
    by nature a mass spectrum is sorted in increasing key (mz) order).
    */
  int m_lastModifIdx = 0;

  //! Tells if data points for which m/z value is 0 should be removed.
  int m_removeZeroValDataPoints = false;

  public:
  Trace();
  Trace(const Trace &other);
  Trace(const QString &title);
  Trace(const QVector<double> &keys, const QVector<double> &values);
  virtual ~Trace();

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

  virtual void reset();
  void deleteDataPoints();

  QString title() const;

  void setDecimalPlaces(int decimalPlaces);
  int decimalPlaces();
  int &rdecimalPlaces();

  virtual int initialize(const QString &xyFormatString);

  int initialize(const Trace &other);

  virtual int initialize(const QList<double> &keyList,
                         const QList<double> &valList);

  virtual int initialize(const QList<double> &keyList,
                         const QList<double> &valList,
                         double keyStart,
                         double keyEnd);

  virtual int initialize(const QVector<double> &keyVector,
                         const QVector<double> &valVector,
                         double keyStart = qSNaN(),
                         double keyEnd   = qSNaN());

  virtual int initialize(const QByteArray *keyByteArray,
                         const QByteArray *valByteArray,
                         int compressionType,
                         double keyStart = qSNaN(),
                         double keyEnd   = qSNaN());

  virtual int removeZeroValDataPoints();

  double valSum() const;
  double valSum(double keyStart, double keyEnd) const;

  int combine(const DataPoint &dataPoint);
  int subtract(const DataPoint &dataPoint);

  int combine(const Trace &other);
  int subtract(const Trace &other);
  int combine(const Trace &other, double keyStart, double keyEnd);
  int subtract(const Trace &other, double keyStart, double keyEnd);

  int combineMonoT(const QList<Trace *> &traceList);
  int combine(const QList<Trace *> &traceList);
  int combineSlice(const QList<Trace *> &traceList, int startIdx, int endIdx);

  int subtractMonoT(const QList<Trace *> &traceList);
  int subtract(const QList<Trace *> &traceList);
  int subtractSlice(const QList<Trace *> &traceList, int startIdx, int endIdx);

  int combine(const QList<Trace *> &traceList, double keyStart, double keyEnd);
  int subtract(const QList<Trace *> &traceList, double keyStart, double keyEnd);

  int combine(const QList<double> &keyList, const QList<double> &valList);
  int subtract(const QList<double> &keyList, const QList<double> &valList);
  int combine(const QList<double> &keyList,
              const QList<double> &valList,
              double keyStart,
              double keyEnd);
  int subtract(const QList<double> &keyList,
               const QList<double> &valList,
               double keyStart,
               double keyEnd);

  int contains(double key) const;
  double valueAt(double key, double tolerance, bool &ok) const;

  QList<double> keyList() const;
  QList<double> valList() const;
  void toLists(QList<double> *keyList, QList<double> *valList) const;
  void toVectors(QVector<double> *keyVector, QVector<double> *valVector) const;
  void toMap(QMap<double, double> *map) const;

  QString asText(int startIndex = -1, int endIndex = -1);

  bool exportToFile(const QString &fileName);
};

} // namespace msXpSlibmass


Q_DECLARE_METATYPE(msXpSlibmass::Trace);
Q_DECLARE_METATYPE(msXpSlibmass::Trace *);

extern int traceMetaTypeId;
extern int tracePtrMetaTypeId;
