/* 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


/////////////////////// Local includes
#include <minexpert/nongui/globals.hpp>
#include <minexpert/nongui/History.hpp>
#include <globals/globals.hpp>
#include <libmass/MsMultiHash.hpp>
#include <libmass/MsMultiHash.hpp>


namespace msXpSmineXpert
{

class MassSpecDataSet;

//! The MassSpecDataStats class provides a structured memory storage for mass
//! data.
/*!

  The MassSpecDataStats class is the in-memory data storage workhorse of
  mineXpert. It allows storing mass spectra in a list and making references to
  the stored mass spectra using maps. In particular, it allows looking for
  spectra on the basis of their retention time or on the basis of their ion
  mobility drift time.

  The structure of MassSpecDataStats is crafted in such a manner that the mass
  spectrum extraction on the basis of various criteria is simple and speedy.

  The mineXpert software may be operated in two modes:

  - streamed, that means that data are systematically read from disk and never
  totally stored in RAM;

  - \e not streamed, that is full, where the data are totally read from disk
  into RAM and used from RAM.

  Member data are designed to allow crafting sub-datasets based on the
  streamed/full requirements above.

  When streamed mode is on (the \c m_isStreamed value is true), the user needs
  to allocate on the heap a new MassSpectrum and append it to the
  m_massSpectra mass spectrum list member because \e that spectrum is going to
  be the combination of the whole set of loaded mass spectra from file.


*/
class MassSpecDataStats
{
  public:
  int m_spectrumCount = 0;

  double m_smallestSpectrumSize = std::numeric_limits<double>::max();
  double m_greatestSpectrumSize = 0;
  double m_spectrumSizeAvg      = 0;
  double m_spectrumSizeStdDev   = 0;

  // First m/z value found in *all* the spectra (that is the minimum m/z
  // value encountered in the whole spectral data set).
  double m_minMz = std::numeric_limits<double>::max();
  // First mz value encountered in any given single mass spectrum
  double m_firstMzAvg    = 0;
  double m_firstMzStdDev = 0;

  // Last m/z value found in *all* the spectra (that is the maximum m/z
  // value encountered in the whole spectral data set).
  double m_maxMz = 0;
  // Last mz value encountered in any given single mass spectrum
  double m_lastMzAvg    = 0;
  double m_lastMzStdDev = 0;

  double m_smallestMzShift = std::numeric_limits<double>::max();
  double m_greatestMzShift = 0;
  double m_mzShiftAvg      = 0;
  double m_mzShiftStdDev   = 0;

  double m_nonZeroSmallestStep = std::numeric_limits<double>::max();
  double m_smallestStep        = std::numeric_limits<double>::max();
  double m_smallestStepMedian  = 0;
  double m_smallestStepAvg     = 0;
  double m_smallestStepStdDev  = 0;

  double m_greatestStep       = 0;
  double m_greatestStepAvg    = 0;
  double m_greatestStepStdDev = 0;

  int m_massToleranceType = msXpS::MassToleranceType::MASS_TOLERANCE_NONE;

  // All the lists used to craft the statistics.
  QList<double> m_spectrumSizeList;

  QList<double> m_firstMzList;
  QList<double> m_lastMzList;

  QList<double> m_mzShiftList;

  QList<double> m_smallestStepList;
  QList<double> m_greatestStepList;
  QList<double> m_avgStepList;
  QList<double> m_stdDevStepList;


  // Helper references to mass spec data.
  MassSpecDataSet *mp_massSpecDataSet;
  QList<msXpSlibmass::MassSpectrum *> *mp_massSpectra;
  History m_history;

  // Construction / Destruction

  MassSpecDataStats();
  MassSpecDataStats(const MassSpecDataStats &other);
  virtual ~MassSpecDataStats();

  MassSpecDataStats &operator=(const MassSpecDataStats &other);

  void reset();

  int spectrumBins(const msXpSlibmass::MassSpectrum &massSpectrum,
                   QList<double> &binList);

  void increment(const msXpSlibmass::MassSpectrum &massSpectrum);
  void consolidate();

  void makeStatistics(const MassSpecDataSet &massSpecDataSet,
                      const History &history);

  bool isValid();

  QString asText();
};


} // namespace msXpSmineXpert
