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


/////////////////////// Local includes
#include <minexpert/nongui/MassSpecSqlite3Handler.hpp>
#include <minexpert/nongui/History.hpp>


namespace msXpSmineXpert
{

//! The SliceType enum defines the way a data slicing operation should be
//! //performed.
/*!

  With mineXpert, it is possible to load a big data file in memory and then
  slice that data file into smaller chunks in new files. This enum elements
  allow to characterize how the slicing should operate.

*/
enum SliceType
{
  SLICE_NOT_SET = 0,
  /*!< The slicing method is not set.*/
  SLICE_ZOOMED_REGION,
  /*!< The slice contains only the data visible in a zoomed region.*/
  SLICE_BY_COUNT,
  /*!< The number of slices is defined and their size depends on the data
     size.*/
  SLICE_BY_SIZE,
  /*!< The size of the slices is defined and their number depends on the data
     size.*/
};


//! The SliceSpecif structure configures a mass data slice.
/*!

  This structure allows to define some characteristics of the slice
  to be created using a SqlMassDataSlicer object.

*/
struct SliceSpecif
{
  QString fileName;
  /*!< Name of the destination file.*/
  double start;
  /*!< Smallest point of the currently visible plot.*/
  double end;
  /*!< Greatest point of the currently visible plot.*/
  int number;
  /*!< Number of slices to produce out of the initial data.*/
};


//! The SqlMassDataSlicer class provides a mass data slicer.
/*!

  With mineXpert, it is possible to load a big data file in memory and then
  slice that data file into smaller chunks in new files. The slicing of mass
  data files can only be performed for files in the SQLite3-based database
  file format.

  The slicing operation is typically performed by selecting in a plot a region
  of interest and then calling the slicing dialog. The data slicing operation
  may be carried over in different ways:

  - by defining the number of slices. In this case the slice size will be
  dependent on the size of the data range selected for the slicing
  operation.

  - by defining a range of the data to be sliced-off the initial data set. In
  this case only one slice is generated matching the range criterion.

  - by defining the size of the slices.	In this case the number of slices
  produces depend on the size of the data range selected for the slicing
  operation.

*/
class SqlMassDataSlicer : public QObject
{
  Q_OBJECT;

  friend class SqlMassDataSlicerJs;


  private:
  //! History instance to characterize the data to be sliced off.
  History m_history;

  //! Name of the file containing the original data.
  QString m_srcFileName;

  //! Name of the directory in which to write the slices.
  QString m_destDirectory;

  //! String describing the naming scheme for the slice files.
  QString m_formatString;

  //! List of specifications containing the details of the slicing operation.
  QList<SliceSpecif *> m_sliceSpecifList;

  //! Type of the slicing operation that is requested.
  int m_sliceType = SliceType::SLICE_NOT_SET;

  //! Smallest value of the range to be sliced off (left range border).
  double m_rangeStart = 0;

  //! Greatest value of the range to be sliced off (right range border).
  double m_rangeEnd = 0;

  //! Number of slices to be generated out of the initial mass data.
  int m_sliceCount = 0;

  //! Size of the slices to be generated.
  double m_sliceSize = 0;

  void clearSliceSpecifications();


  public:
  SqlMassDataSlicer();
  SqlMassDataSlicer(const SqlMassDataSlicer &other);
  SqlMassDataSlicer(History history, double rangeStart, double rangeEnd);
  virtual ~SqlMassDataSlicer();

  SqlMassDataSlicer &initialize(QString fileName,
                                double rangeStart,
                                double rangeEnd,
                                const History &history);
  SqlMassDataSlicer &initialize(const SqlMassDataSlicer &other);
  SqlMassDataSlicer &operator=(const SqlMassDataSlicer &other);

  void reset();

  bool configureSpecifs(QString *errors);

  void setRangeStart(double value);
  double rangeStart() const;
  void setRangeEnd(double value);
  double rangeEnd() const;
  void setRange(double start, double end);

  void setHistory(const History &history);

  void setSliceType(int type);
  void setSliceSize(double size);
  void setSliceCount(int count);

  void setDestDirectory(QString dir);
  QString destDirectory() const;

  void setSrcFileName(QString fileName);
  QString srcFileName() const;

  void setFormatString(QString format);
  QString formatString() const;

  QString craftSliceFileName(SliceSpecif *sliceSpecif) const;
  QString allFileNamesAsString() const;

  QString slice(MassSpecSqlite3Handler *mp_sqlHandler);

  QString asText() const;
  QString sliceSpecifAsText(SliceSpecif *specif) const;
  QString allSliceSpecifsAsText() const;


  signals:
  void updateSliceFileName(QString fileName);
};

extern QMap<int, QString> sliceTypeMap;

} // namespace msXpSmineXpert

Q_DECLARE_METATYPE(msXpSmineXpert::SliceSpecif);
Q_DECLARE_METATYPE(msXpSmineXpert::SqlMassDataSlicer);
Q_DECLARE_METATYPE(msXpSmineXpert::SqlMassDataSlicer *);

extern int SliceSpecifMetaTypeId;
extern int sqlMassDataSlicerMetaTypeId;
extern int sqlMassDataSlicerPtrMetaTypeId;
