/* 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 <QtSql>
#include <QSqlDatabase>
#include <QStringList>

/////////////////////// Local includes
#include <minexpert/nongui/globals.hpp>
#include <minexpert/nongui/SqlTableFieldSpecifs.hpp>
#include <minexpert/nongui/SqlTableSpecifs.hpp>
#include <minexpert/nongui/MassSpecFileMetaData.hpp>
#include <minexpert/nongui/MassSpecDataSet.hpp>
#include <libmass/MassSpectrum.hpp>
#include <minexpert/nongui/History.hpp>


namespace msXpSmineXpert
{

class AbstractPlotWidget;


//! The MassSpecSqlite3Handler class provides a SQLite3 database handler.
/*!

  The SQLite3 database handler is responsible for:

  -	the creation of mineXpert-specific database files, that is, the creation
  of the required tables;

  - the writing of mass data to the database (in particular when converting
  files from the mzML format);

  - the reading of mass data from the database file.

  \sa FileFormatConverter <br> MassSpecDataFileLoaderSqlite3 <br>
  MassSpecDataFileLoaderPwiz.

*/
class MassSpecSqlite3Handler : public QObject
{
  Q_OBJECT;

  friend class FileFormatConverter;
  friend class MassSpecDataFileLoaderSqlite3;
  friend class MassSpecDataFileLoaderPwiz;

  private:
  //! The name of the database file.
  QString m_dbFileName;

  //! Metadata to use for fill-in the metaData table.
  /*!

    When writing the database file, the metadata are collected progressively
    throughout the reading of the mzML file and are thus stored in this
    member. The metadata are written to the table as the last information bit
    in the database.

*/
  MassSpecFileMetaData m_msFileMetaData;

  //! The number of spectra that need to be read before crafting...
  /*!

    This is the number of spectra that need to be read before crafting a
    feedback message to display to the user, either in the graphical user
    interface or in the terminal window.

*/
  int m_parseProgressionNumber = 100;

  int m_progressFeedbackStartValue = -1;
  int m_progressFeedbackEndValue   = -1;

  //! Specifications to create the metaData table.
  SqlTableSpecifs m_metaDataTableSpecifs;

  //! Specifications to create the spectralData table.
  SqlTableSpecifs m_spectralDataTableSpecifs;

  //! Specifications to create the driftData table.
  SqlTableSpecifs m_driftDataTableSpecifs;


  bool createMetaDataTableSpecifs();
  QString
  metaDataTableInsertSqlCommand(const MassSpecFileMetaData &specMetaData);
  bool writeDbMassSpecFileMetaData(QSqlDatabase &database,
                                   const MassSpecFileMetaData &specMetaData);

  bool createDriftDataTableSpecifs();
  bool
  writeDbDriftData(QSqlDatabase &database, double driftTime, int *recordId);

  bool createSpectralDataTableSpecifs();
  bool writeDbSpectralData(QSqlDatabase &database,
                           int idx,
                           const QString &title,
                           int peakCount,
                           int msLevel,
                           double tic,
                           double scanStartTime,
                           int driftDataId,
                           double mzStart,
                           double mzEnd,
                           const QByteArray &mzByteArray,
                           const QByteArray &iByteArray);

  QString tableCreationSqlCommand(QString tableName);
  bool createDbTables(QSqlDatabase &databse);


  public:
  MassSpecSqlite3Handler();
  ~MassSpecSqlite3Handler();

  bool initializeDbForRead(QSqlDatabase &database, bool readMetaData = false);
  bool initializeDbForWrite(QSqlDatabase &database);

  void setDbFileName(const QString &fileName);

  MassSpecFileMetaData getMassSpecFileMetaDataFromDb(QSqlDatabase &database);

  int spectrumListCount(QSqlDatabase &database);

  QList<double> rtList(QSqlDatabase &database);

  void mzRange(QSqlDatabase &database, double &mzStart, double &mzEnd);

  bool isDriftExperiment(QSqlDatabase &database);
  QList<double> *driftTimeList(QSqlDatabase &database);

  bool exportData_metaData(QSqlDatabase &srcDatabase,
                           QSqlDatabase &dstDatabase,
                           int spectrumListCount);
  bool exportData_driftData(QSqlDatabase &srcDatabase,
                            QSqlDatabase &dstDatabase);
  QString
  exportData(QSqlDatabase &srcDatabase, QString dstFileName, History history);
  QString exportData(QString srcFileName, QString dstFileName, History history);


  signals:
  void dataLoadMessageSignal(QString msg, int logType);
  void dataLoadProgressSignal(int spectrumIndex);

  void updateFeedbackSignal(QString msg,
                            int currentValue,
                            bool setVisible,
                            int logType,
                            int startValue = -1,
                            int endValue   = -1);
};

} // namespace msXpSmineXpert
// namespace msXpSmineXpert
