/* 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 <QList>
#include <QDateTime>
#include <QMap>


/////////////////////// Local includes
#include <globals/globals.hpp>


namespace msXpSmineXpert
{


//! Enum to define the kind of mass data integration
/*!

  Analyzing mass spectrometric data involves performing integration of many
  different kinds. For example, once can integrate all the mass spectra
  acquired between two retention time values and produce a mass spectrum; or
  one can integrate between the same retention time values but produce not a
  mass spectrum, but a drift spectrum. Another integration could be to make a
  drift spectrum with all the spectra that were acquired between two m/z
  values in a given mass spectrum, which would mean "show me the drift times
  of all the ions that were observed in this spectrum between m/z value and
  m/z value. The members of this enumeration serve to define more or less
  precisely the kind of integration that is being performed. This information
  is important to document what a given trace (be that trace a TIC
  chromatogram, a XIC chromatogram, a mass spectrum or a drift spectrum)
  contains with respect to the initial data contained in the mass spectrometry
  data file because the user will want to refer to that information to
  actually mine the data.

*/
enum IntegrationType
{
  NOT_SET = 0x0000,

  FILE_TO_RT = 1 << 0,
  /*!< Integrate from mass data file to retention time (TIC chromatogram) */

  FILE_TO_MZ = 1 << 1,
  /*!< Integrate from mass data file to retention time (TIC chromatogram) */

  FILE_TO_DT = 1 << 2,
  /*!< Integrate from mass data file to retention time (TIC chromatogram) */

  FILE_TO_XIC = 1 << 3,
  /*!< Integrate from mass data file to retention time (XIC chromatogram) */

  RT_TO_MZ = 1 << 4,
  /*!< Integrate from TIC or XIC chromatogram to mass spectrum */

  RT_TO_DT = 1 << 5,
  /*!< Integrate from TIC or XIC chromatogram to drift spectrum */

  RT_TO_TIC_INT = 1 << 6,
  /*!< Integrate from TIC chrom range to TIC intensity single value */

  MZ_TO_RT = 1 << 7,
  /*!< Integrate from mass spectrum to XIC chromatogram (retention time) */

  MZ_TO_MZ = 1 << 8,
  /*!< Integrate from mass spectrum to mass spectrum (from color map)*/

  MZ_TO_DT = 1 << 9,
  /*!< Integrate from mass spectrum to drift spectrum*/

  MZ_TO_TIC_INT = 1 << 10,
  /*!< Integrate from mass spectrum range to TIC intensity single value */

  DT_TO_RT = 1 << 11,
  /*!< Integrate from drift spectrum to XIC (retention time) */

  DT_TO_MZ = 1 << 12,
  /*!< Integrate from drift spectrum to mass spectrum */

  DT_TO_DT = 1 << 13,
  /*!< Integrate from drift spectrum to drift spectrum (from color map)*/

  DT_TO_TIC_INT = 1 << 14,
  /*!< Integrate from drift spectrum range to TIC intensity single value */

  // Now the specific color map integration types:
  DTMZ_DT_TO_RT = 1 << 15,
  /*!< Integrate from mz/dt color map, dt range, to retention time (XIC
     chromatogram) */

  DTMZ_MZ_TO_RT = 1 << 16,
  /*!< Integrate from mz/dt color map, mz range, to retention time (XIC
     chromatogram) */

  // Now the specific color map integration types:
  DTMZ_DT_TO_MZ = 1 << 17,
  /*!< Integrate from mz/dt color map, dt range, to mass spectrum */

  DTMZ_MZ_TO_MZ = 1 << 18,
  /*!< Integrate from mz/dt color map, mz range, to mass spectrum */

  // Now the specific color map integration types:
  DTMZ_DT_TO_DT = 1 << 19,
  /*!< Integrate from mz/dt color map, dt range, to drift spectrum */

  DTMZ_MZ_TO_DT = 1 << 20,
  /*!< Integrate from mz/dt color map, mz range, to drift spectrum */

  // Now the specific color map integration types:
  DTMZ_DT_TO_TIC_INT = 1 << 21,
  /*!< Integrate from mz/dt color map, dt range, to TIC intensity value */

  DTMZ_MZ_TO_TIC_INT = 1 << 22,
  /*!< Integrate from mz/dt color map, mz range, to TIC intensity value */

  // Now the generic XXX_TO_YY
  XXX_TO_RT      = 1 << 23,
  XXX_TO_MZ      = 1 << 24,
  XXX_TO_DT      = 1 << 25,
  XXX_TO_TIC_INT = 1 << 26,

  // And the generic YY_TO_XXX
  RT_TO_XXX = 1 << 27,
  MZ_TO_XXX = 1 << 28,
  DT_TO_XXX = 1 << 29,

  RT_TO_ANY = (RT_TO_XXX | RT_TO_MZ | RT_TO_DT | RT_TO_TIC_INT),

  MZ_TO_ANY =
    (MZ_TO_XXX | MZ_TO_RT | DTMZ_MZ_TO_RT | DTMZ_MZ_TO_MZ | DTMZ_MZ_TO_DT |
     FILE_TO_XIC | MZ_TO_MZ | MZ_TO_DT | MZ_TO_TIC_INT),

  DT_TO_ANY = (DT_TO_XXX | DT_TO_RT | DTMZ_DT_TO_RT | DTMZ_DT_TO_MZ |
               DTMZ_DT_TO_DT | DT_TO_MZ | DT_TO_DT | DT_TO_TIC_INT),

  ANY_TO_RT = (XXX_TO_RT | FILE_TO_RT | FILE_TO_XIC | MZ_TO_RT | DT_TO_RT |
               DTMZ_DT_TO_RT | DTMZ_MZ_TO_RT),

  ANY_TO_MZ = (XXX_TO_MZ | FILE_TO_MZ | RT_TO_MZ | MZ_TO_MZ | DT_TO_MZ |
               DTMZ_DT_TO_MZ | DTMZ_MZ_TO_MZ),

  ANY_TO_DT = (XXX_TO_DT | FILE_TO_DT | RT_TO_DT | MZ_TO_DT | DT_TO_DT |
               DTMZ_DT_TO_DT | DTMZ_MZ_TO_DT),

  ANY_TO_TIC_INT = (XXX_TO_TIC_INT | RT_TO_TIC_INT | MZ_TO_TIC_INT |
                    DT_TO_TIC_INT | DTMZ_DT_TO_TIC_INT | DTMZ_MZ_TO_TIC_INT),
};


//! The IntegrationRange structure describes a range of integration
/*!

  When performing a data integration, like creating a mass spectrum starting
  from a TIC chromatogram, the user typically selects a TIC chromatogram
  retention time range for which to combine the mass spectra acquired during
  that time range into a single spectrum.

  Note that the \c start and \c end values of the range are to be considered
  part of the range, that is the range is [\c start -- \c end].

*/
struct IntegrationRange
{
  double start;
  /*!< start (left) value of the range */

  double end;
  /*!< end (right) value of the range */
};


//! The IntegrationTypeDesc structure defines a description of a data
//! integration
/*!

  The IntegrationTypeDesc structure helps maintaining a detailed record of the
  various integrations that are performed in the course of data mining of mass
  spectrometry data. This helper structure gathers two textual representations
  of a given data integration step.

*/
struct IntegrationTypeDesc
{
  QString detailed;
  /*!< Detailed textual representation of an integration step */

  QString brief;
  /*!< Brief textual representation of an integration step */
};


//! The HistoryItem class provides a single element that can be part of a
//! History
/*!

  When the user performs data integration in the course of mass spectrometric
  data analysis, it is necessary that the various integration steps be stored
  as meaningful data bits, both for the program to know where a given trace
  (mass spec, drift spec or chromatogram, for exemple) originates from and for
  the user to understand the various data mining results that are a result of
  the way the data integrations were performed in sequence during the data
  mining session.

  This class provides two map member data to put in correspondence:

  -	IntegrationType keys with IntegrationTypeDesc pointers

  - IntegrationType keys with IntegrationRange pointers

*/
class HistoryItem
{

  friend class History;

  private:
  void prepareIntegrationTypeDescriptionMap();

  static bool m_mapPrepared;

  //! Date and time stamp of this HistoryItem instance
  QDateTime m_dateTime;

  //! Map relating IntegrationType keys to pointers to IntegrationRange values
  /*!

    Note that the IntegrationRange instances are owned by \c this instance
    and are destroyed by the destructor.

*/
  QMap<int /* IntegrationType */, IntegrationRange *> m_integrationMap;

  public:
  //! Map relating IntegrationType keys to pointers to IntegrationTypeDesc
  //! values
  /*!

    This map is initialized upon construction of the HistoryItem instance
    and is regarded as, somehow, a "static" member map because it never
    changes from an instance and the others.

    Note that the IntegrationTypeDesc instances are owned by \c this
    instance and are destroyed by the destructor.

*/
  static QMap<int /* IntegrationType */, IntegrationTypeDesc *>
    m_integrationTypeDescriptionMap;

  HistoryItem();
  HistoryItem(const HistoryItem &other);
  HistoryItem &operator=(const HistoryItem &other);
  ~HistoryItem();

  bool operator==(const HistoryItem &other) const;
  HistoryItem &initialize(const HistoryItem &other);
  bool contains(int intType, const IntegrationRange &intRange) const;

  void setDateTime();
  QDateTime dateTime() const;

  void newIntegrationRange(int intType, double start, double end);

  bool hasIntegrationType(int intType);
  IntegrationRange *integrationRange(int intType) const;
  int integrationType(IntegrationRange *integrationRange);

  QList<int> integrationTypes() const;
  QList<IntegrationRange *> integrationRanges() const;

  bool isValid() const;

  QString asText(bool brief = false) const;
};


} // namespace msXpSmineXpert

Q_DECLARE_METATYPE(msXpSmineXpert::HistoryItem);
extern int historyItemMetaTypeId;
