/**
 * \file pappsomspp/types.h
 * \date 4/3/2015
 * \author Olivier Langella
 * \brief This header contains all the type re-definitions and all
 * the global variables definitions used in the PAPPSOms++ library.
 */

/*******************************************************************************
 * Copyright (c) 2015 Olivier Langella <Olivier.Langella@moulon.inra.fr>.
 *
 * This file is part of the PAPPSOms++ library.
 *
 *     PAPPSOms++ 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.
 *
 *     PAPPSOms++ 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 PAPPSOms++.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@moulon.inra.fr> - initial API and
 *implementation
 ******************************************************************************/

#pragma once

/////////////////////// stdlib includes
#include <cstdint>
#include <map>


/////////////////////// Qt includes
#include <QString>


/////////////////////// Local includes
#include "pappsomspp/export-import-config.h"
#include "pappsomspp/config.h"


namespace pappso
{
/************ Typedefs **************************************************/

/** \var typedef QString PeptideStr
 \brief A type definition for PeptideStr
 */
typedef QString PeptideStr;

/** \var typedef double pappso_double
 \brief A type definition for doubles
 */
typedef double pappso_double;

/** \var typedef float mcq_float
 \brief A type definition for floats
 */
typedef float pappso_float;

typedef unsigned int uint;


namespace Enums
{
// This will have the effect of creating a static pappso::Enums
// QMetaObject that can then be exposed to QJSEngine and QQmlEngine.
// See pappsojsqml.cpp, function registerEnumsToQJSEngine().
// Attention, for the static MetaObject to be effectively exported,
// the types.cpp file is required. Check it!
PMSPP_LIB_DECL Q_NAMESPACE

  /*********** enumerations *********************************/


  /** \def TimeUnit (s, min, h)
   */
  enum class TimeUnit {
    none,
    s,
    min,
    h,
  };


/** \def PrecisionUnit ppm or dalton
 *
 */
enum class PrecisionUnit
{
  none,
  dalton,
  ppm,
  res,
  mz,
  last
};
Q_ENUM_NS(PrecisionUnit)

/** \def AtomIsotopeSurvey list of atoms on which isotopes may occurs
 *
 */
enum class AtomIsotopeSurvey : std::int8_t
{
  C,
  H,
  O,
  N,
  S,
  P,
  last
};


/** \def Isotope list of isotopes taken into account for peptide abundance
 * calculation
 *
 */
enum class Isotope
{
  C,
  C13,
  H,
  H2,
  O,
  O17,
  O18,
  N,
  N15,
  S,
  S33,
  S34,
  S36,
  P
};


/** \def MzFormat mz data file format types
 *
 */
enum class MsDataFormat : std::int8_t
{
  unknown           = 0, ///< unknown format
  mzML              = 1, ///< mzML
  mzXML             = 2, ///< mzXML
  MGF               = 3, ///< Mascot format
  SQLite3           = 4, ///< SQLite3 format
  xy                = 5, ///< (x,y) format
  mz5               = 6, //< MZ5 format
  msn               = 7, //< MS_MS2 format
  abSciexWiff       = 8,
  abSciexT2D        = 9,
  agilentMassHunter = 10,
  thermoRaw         = 11,
  watersRaw         = 12,
  brukerFid         = 13,
  brukerYep         = 14,
  brukerBaf         = 15,
  brukerTims        = 16,
  brukerBafAscii    = 17, // Baf to ascii from Bruker software
  mzcbor            = 18,
  last              = 19
};
Q_ENUM_NS(MsDataFormat)

/** \def FileReaderType mass data file reader types
 *
 */
enum class FileReaderType
{
  pwiz, ///< using libpwizlite
  mzcbor, ///< using homemade mzcbor parser
  xy,
  bafascii,
  tims,        ///< TimsMsRunReader : each scan is returned as a mass spectrum
  tims_frames, ///< TimsFramesMsRunReader : the whole frame is merged in a
               ///< single spectrum
  tims_ms2,    ///< TimsMsRunReaderMs2 : Spectrum are delivered for each precursor
               ///< (MS1 or MS2)

  tims_dia, ///< TimsMsRunReaderDia : Spectrum are delivered for DIA window
            ///< (slice)
};
Q_ENUM_NS(FileReaderType)

/** \def AminoAcidChar Amino-acid full name and code correspondence
 *
 */
enum class AminoAcidChar : char
{
  alanine        = 'A',
  cysteine       = 'C',
  aspartic_acid  = 'D',
  glutamic_acid  = 'E',
  phenylalanine  = 'F',
  glycine        = 'G',
  histidine      = 'H',
  isoleucine     = 'I',
  lysine         = 'K',
  leucine        = 'L',
  methionine     = 'M',
  asparagine     = 'N',
  proline        = 'P',
  glutamine      = 'Q',
  arginine       = 'R',
  serine         = 'S',
  threonine      = 'T',
  valine         = 'V',
  tryptophan     = 'W',
  tyrosine       = 'Y',
  selenocysteine = 'U',
  pyrrolysine    = 'O',
};


enum class SortType : std::int8_t
{
  none = 0,
  x    = 1,
  y    = 2,
};
Q_ENUM_NS(SortType)

enum class SortOrder : std::int8_t
{
  ascending  = 0,
  descending = 1,
};
Q_ENUM_NS(SortOrder)

/** \def Data compression types
 *
 */
enum class DataCompression : std::int8_t
{
  unset = -1, ///< not net
  none  = 0,  ///< no compression
  zlib  = 1,  ///< zlib compresssion
};
Q_ENUM_NS(DataCompression)

enum class DataKind : std::int8_t
{
  unset = -1, ///< not set
  rt    = 0,  ///< Retention time
  dt    = 1,  ///< Drift time
  mz    = 2,  ///< m/z
};
Q_ENUM_NS(DataKind)

enum class Axis : std::int8_t
{
  unset = 0x000,
  x     = 1 << 0,
  y     = 1 << 1,
  z     = 1 << 2,
};
Q_ENUM_NS(Axis)

enum class AxisScale : std::int8_t
{
  unset = 0,
  orig  = 1,
  log10 = 2,
};
Q_ENUM_NS(AxisScale)

/** \def XixExtactMethod method to extract Xic
 *
 */
enum class XicExtractMethod : std::int8_t
{
  sum = 1, ///< sum of intensities
  max = 2  ///< maximum of intensities
};

/** \brief Enums::PeptideIon enum defines all types of ions (Nter or Cter)
 */
enum class PeptideIon : std::int8_t
{
  b     = 0, ///< Nter acylium ions
  bstar = 1, ///< Nter acylium ions + NH3 loss
  bo    = 2, ///< Nter acylium ions + H2O loss
  a     = 3, ///< Nter aldimine ions
  astar = 4, ///< Nter aldimine ions + NH3 loss
  ao    = 5, ///< Nter aldimine ions + H2O loss
  bp    = 6,
  c     = 7,  ///< Nter amino ions
  y     = 8,  ///< Cter amino ions
  ystar = 9,  ///< Cter amino ions + NH3 loss
  yo    = 10, ///< Cter amino ions + H2O loss
  z     = 11, ///< Cter carbocations
  yp    = 12,
  x     = 13 ///< Cter acylium ions
};

} // namespace Enums

extern std::map<Enums::DataKind, QString> dataKindMap;
extern std::map<Enums::PrecisionUnit, QString> precisionUnitMap;


/*********** Global variables definitions*********************************/

/** \def MHPLUS 1.007276466879
 \brief The (monoisotopic) mass of the H+ ion
 https://en.wikipedia.org/wiki/Proton (One Proton alone)
 1.007276466879
 */
const pappso_double MHPLUS(1.007276466879);
const pappso_double MPROTON(1.007276466879);

/** \def MPROTIUM 1.00782503207
 \brief The (monoisotopic) mass of the H atom
 https://en.wikipedia.org/wiki/Isotopes_of_hydrogen (One proton + One electron)
 1.00782503207

 Note that as of 20191028, that same page says: 1.007825032241
 */
const pappso_double MPROTIUM(1.007825032241);


/** \def ONEMILLION 1000000
 \brief One million integer, why not.
 */
const pappso_double ONEMILLION(1000000);


/** @file
 * https://forgemia.inra.fr/pappso/massxpert/-/blob/be60e53480f68d36afa95c809cffd68d4fb46c79/data/polChemDefs/protein-1-letter-libisospec-atomic-data/protein-1-letter-libisospec-atomic-data.xml
 * abundance of sulfur extracted from 'massXpert' polymer definitions
 */
// <name>Sulfur</name>
//			<symbol>S</symbol>
//			<isotope>
//				<mass>31.9720711741</mass>
//				<abund>94.985001199904004920426814351230859756469726562500000000000000</abund>
//			</isotope>
//			<isotope>
//				<mass>32.9714589101</mass>
//				<abund>0.751939844812414937003097747947322204709053039550781250000000</abund>
//			</isotope>
//			<isotope>
//				<mass>33.9678670300</mass>
//				<abund>4.252059835213182203972337447339668869972229003906250000000000</abund>
//			</isotope>
//			<isotope>
//				<mass>35.9670812000</mass>
//				<abund>0.010999120070394368536836893213148869108408689498901367187500</abund>
//			</isotope>


const pappso_double MASSOXYGEN(15.99491461956);
const pappso_double MASSCARBON(12);
const pappso_double MASSH2O((MPROTIUM * 2) + MASSOXYGEN);
const pappso_double MASSNITROGEN(14.0030740048);
const pappso_double MASSNH3((MPROTIUM * 3) + MASSNITROGEN);
const pappso_double MASSCO(MASSCARBON + MASSOXYGEN);
const pappso_double MASSPHOSPHORUS(30.973761998);
const pappso_double MASSSULFUR(31.9720711741);

// id: MOD:00696 name: phosphorylated residue H 1 O 3 P 1
const pappso_double MASSPHOSPHORYLATEDR(MPROTIUM + (MASSOXYGEN * 3) + MASSPHOSPHORUS);

// Selenium : warning lot of isotopes
const pappso_double MASSSELENIUM(79.916520); // 79.916520 //78.971

// CHNOS

/** \def DIFFC12C13 1.0033548378
 \brief The (monoisotopic) mass difference between C12 (12u) and C13 stable
 isotope of carbon
 */
const pappso_double DIFFC12C13(1.0033548378);

/** \def DIFFS32S33 0.99938776
 \brief The (monoisotopic) mass difference between S32 (31.97207100u) and S33
 (32.97145876u) stable isotope of sulfur
 https://en.wikipedia.org/wiki/Isotopes_of_sulfur
 */
const pappso_double DIFFS32S33(32.9714589101 - MASSSULFUR);

/** \def DIFFS32S34 1.9957959
 \brief The (monoisotopic) mass difference between S32 (31.97207100u) and S34
 (33.96786690u) stable isotope of sulfur
 */
const pappso_double DIFFS32S34(33.9678670300 - MASSSULFUR);

/** \def DIFFS32S36 3.99500976
 \brief The (monoisotopic) mass difference between S32 (31.97207100u) and S36
 (35.96708076u) stable isotope of sulfur
 */
const pappso_double DIFFS32S36(35.9670812000 - MASSSULFUR);


/** \def DIFFH1H2
 \brief The (monoisotopic) mass difference between H1 and H2 stable isotope of
 hydrogen
 */
const pappso_double DIFFH1H2(2.0141017778 - MPROTIUM);

/** \def DIFFO16O18
 \brief The (monoisotopic) mass difference between O16 and O18 stable isotope of
 oxygen
 */
const pappso_double DIFFO16O18(17.9991610 - MASSOXYGEN);

/** \def DIFFO16O17
 \brief The (monoisotopic) mass difference between O16 and O17 stable isotope of
 oxygen
 */
const pappso_double DIFFO16O17(16.99913150 - MASSOXYGEN);

/** \def DIFFN14N15
 \brief The (monoisotopic) mass difference between N14 and N15 stable isotope of
 nitrogen
 */
const pappso_double DIFFN14N15(15.0001088982 - MASSNITROGEN);


// http://education.expasy.org/student_projects/isotopident/htdocs/motza.html
/** \def ABUNDANCEH2 0.0156%
 \brief H2 isotope abundance
 */
const pappso_double ABUNDANCEH2(0.00011570983569203332000374651045149221317842602729797363281250);

/** \def ABUNDANCEN15 0.00364
 \brief N15 isotope abundance
 */
const pappso_double ABUNDANCEN15(0.00364198543205827118818262988497735932469367980957031250000000);

/** \def ABUNDANCEO17
 \brief O17 isotope abundance
 */
const pappso_double ABUNDANCEO17(0.00038099847600609595965615028489992255344986915588378906250000);

/** \def ABUNDANCEO18 0.2%
 \brief O18 isotope abundance
 */
const pappso_double ABUNDANCEO18(0.00205139179443282221315669744399201590567827224731445312500000);

/** \def ABUNDANCEC13 1.109%
 \brief C13 isotope abundance
 */
const pappso_double ABUNDANCEC13(0.01078805814953308406245469086570665240287780761718750000000000);

/** \def ABUNDANCEC12 98.89%
 \brief C12 abundance
 */
const pappso_double ABUNDANCEC12(0.98921194185046687152862432412803173065185546875000000000000000);


/** \def ABUNDANCES33 0.00750
 \brief S33 abundance
 */
const pappso_double ABUNDANCES33(0.00751939844812414937003097747947322204709053039550781250000000);

/** \def ABUNDANCES34 0.0429
 \brief S34 abundance
 */
const pappso_double ABUNDANCES34(0.04252059835213182203972337447339668869972229003906250000000000);

/** \def ABUNDANCES36 0.00020
 \brief S36 abundance
 */
const pappso_double ABUNDANCES36(0.00010999120070394368536836893213148869108408689498901367187500);


/** \brief only useful for internal use
 * DO not change this value : it is used to define static array size
 */
#define PEPTIDE_ION_TYPE_COUNT 14

} // namespace pappso
