/* BEGIN software license
 *
 * MsXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright 2009--2026 by 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

////////////////////////////// Stdlib includes
#include <map>


////////////////////////////// Qt includes
#include <QString>
#include <QList>
#include <QTextStream>
#include <QRegularExpression>


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

/*
 Bitwise stuff (from StackOverflow)

 It is sometimes worth using an enum to name the bits:

 enum ThingFlags = {
 ThingMask  = 0x0000,
 ThingFlag0 = 1 << 0,
 ThingFlag1 = 1 << 1,
 ThingError = 1 << 8,
 }

 Then use the names later on. I.e. write

 thingstate |= ThingFlag1;
 thingstate &= ~ThingFlag0;
 if (thing & ThingError) {...}

 to set, clear and test. This way you hide the magic numbers from the rest of
 your code.
 */

namespace MsXpS
{
namespace libXpertMassCore
{


// Macro to fake qFatal() << streaming in Qt 6.4
#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0) // If Qt < 6.8
#define qFatalStream()                             \
  for(QString fatalMsg; fatalMsg.isEmpty();        \
      qFatal("%s", fatalMsg.toUtf8().constData())) \
  QDebug(&fatalMsg).noquote().nospace()
#else
#define qFatalStream() qFatal()
#endif


/////////////////////////// namespace Enums ////////////////////////////
/////////////////////////// namespace Enums ////////////////////////////
/////////////////////////// namespace Enums ////////////////////////////

namespace Enums
{
DECLSPEC Q_NAMESPACE

  enum class LocationType
{
  INDEX    = 0,
  POSITION = 1,
};
Q_ENUM_NS(LocationType)

enum class MassType
{
  MONO = 1 << 0,      //!< Monoisotopic mass
  AVG  = 1 << 1,      //!< Average mass
  BOTH = (MONO | AVG) //!< Both masses
};
Q_ENUM_NS(MassType)

// Overload bitwise AND operator
inline MassType
operator&(MassType lhs, MassType rhs)
{
  return static_cast<MassType>(
    static_cast<std::underlying_type_t<MassType>>(lhs) &
    static_cast<std::underlying_type_t<MassType>>(rhs));
}

enum class PolChemDefEntityStatus
{
  POL_CHEM_DEF_NOT_AVAILABLE = 0,
  ENTITY_NOT_KNOWN,
  ENTITY_KNOWN
};
Q_ENUM_NS(PolChemDefEntityStatus)

enum class MassToleranceType
{
  NONE = 0,
  //!< parts per million
  PPM,
  //!< m/z ratio
  MZ,
  //!< atomic mass units
  AMU,
  //!< resolution, that is [1 / m/z]
  RES,
  LAST
};
Q_ENUM_NS(MassToleranceType)

enum class PolymerEnd
{
  NONE  = 0 << 1,
  LEFT  = 1 << 1,
  RIGHT = 2 << 1,
  BOTH  = (LEFT | RIGHT)
};
Q_ENUM_NS(PolymerEnd)

// Overload bitwise AND operator
inline PolymerEnd
operator&(PolymerEnd lhs, PolymerEnd rhs)
{
  return static_cast<PolymerEnd>(
    static_cast<std::underlying_type_t<PolymerEnd>>(lhs) &
    static_cast<std::underlying_type_t<PolymerEnd>>(rhs));
}

enum IonizationOutcome
{
  FAILED    = 0,
  UNCHANGED = 1,
  IONIZED   = 2,
  DEIONIZED = 3,
};
Q_ENUM_NS(IonizationOutcome)

enum class SelectionType
{
  RESIDUAL_CHAINS,
  OLIGOMERS
};
Q_ENUM_NS(SelectionType)

enum class CapType
{
  NONE  = 0 << 1,
  LEFT  = 1 << 1,
  RIGHT = 2 << 1,
  BOTH  = (LEFT | RIGHT)
};
Q_ENUM_NS(CapType)

// Overload bitwise AND operator
inline CapType
operator&(CapType lhs, CapType rhs)
{
  return static_cast<CapType>(
    static_cast<std::underlying_type_t<CapType>>(lhs) &
    static_cast<std::underlying_type_t<CapType>>(rhs));
}

//! Chemical entities.
enum class ChemicalEntity
{
  NONE                   = 0,
  MONOMER                = 1 << 0,
  MODIF                  = 1 << 1,
  CROSS_LINKER           = 1 << 2,
  MODIF_AND_CROSS_LINKER = (MODIF | CROSS_LINKER),
  CROSS_LINK             = 1 << 3,
  LEFT_END_MODIF         = 1 << 4,
  FORCE_LEFT_END_MODIF   = 1 << 5,
  RIGHT_END_MODIF        = 1 << 6,
  FORCE_RIGHT_END_MODIF  = 1 << 7,
  BOTH_END_MODIFS        = (LEFT_END_MODIF | RIGHT_END_MODIF),
  FORCE_BOTH_END_MODIFS  = (FORCE_LEFT_END_MODIF | FORCE_RIGHT_END_MODIF)
};
Q_ENUM_NS(ChemicalEntity)

// Overload bitwise AND operator
inline Enums::ChemicalEntity
operator&(Enums::ChemicalEntity lhs, Enums::ChemicalEntity rhs)
{
  return static_cast<ChemicalEntity>(
    static_cast<std::underlying_type_t<ChemicalEntity>>(lhs) &
    static_cast<std::underlying_type_t<ChemicalEntity>>(rhs));
}

enum class CrossLinkEncompassed
{
  NOT       = 0,
  PARTIALLY = 1,
  FULLY     = 2,
};
Q_ENUM_NS(CrossLinkEncompassed)

enum class HashAccountData
{
  NOTHING       = 0x0,
  SEQUENCE      = 1 << 0,
  MONOMER_MODIF = 1 << 1,
  POLYMER_MODIF = 1 << 2
};
Q_ENUM_NS(HashAccountData)

enum class CleavageAction
{
  NOT_SET   = -1,
  NO_CLEAVE = 0,
  CLEAVE    = 1,
};
Q_ENUM_NS(CleavageAction)

enum class FragEnd
{
  NE = 0x0,
  LE = 1 << 0,
  RE = 1 << 1,
  BE = (LE | RE),
};
Q_ENUM_NS(FragEnd)

// Overload bitwise AND operator
inline FragEnd
operator&(FragEnd lhs, FragEnd rhs)
{
  return static_cast<FragEnd>(
    static_cast<std::underlying_type_t<FragEnd>>(lhs) &
    static_cast<std::underlying_type_t<FragEnd>>(rhs));
}

enum class ChemicalGroupTrapped
{
  NEVER = 0x0,
  LEFT  = 1 << 0,
  RIGHT = 1 << 1,
};
Q_ENUM_NS(ChemicalGroupTrapped)

// Overload bitwise AND operator
inline ChemicalGroupTrapped
operator&(ChemicalGroupTrapped lhs, ChemicalGroupTrapped rhs)
{
  return static_cast<ChemicalGroupTrapped>(
    static_cast<std::underlying_type_t<ChemicalGroupTrapped>>(lhs) &
    static_cast<std::underlying_type_t<ChemicalGroupTrapped>>(rhs));
}

enum class ChemicalGroupFate
{
  LOST      = 0,
  PRESERVED = 1,
};
Q_ENUM_NS(ChemicalGroupFate)

enum class MassPeakShapeType
{
  NOT_SET = 0,
  GAUSSIAN,
  LORENTZIAN,
};
Q_ENUM_NS(MassPeakShapeType)

enum class MassPeakWidthLogic
{
  NOT_SET = 0,
  FWHM,
  RESOLUTION
};
Q_ENUM_NS(MassPeakWidthLogic)

enum class MassDataType
{
  NOT_SET = 0,
  MASS_SPECTRUM,
  DRIFT_SPECTRUM,
  TIC_CHROMATOGRAM,
  XIC_CHROMATOGRAM,
  MZ_RT_COLORMAP,
  DT_RT_COLORMAP,
  DT_MZ_COLORMAP,
  LAST,
};
Q_ENUM_NS(MassDataType)


} // namespace Enums

extern DECLSPEC std::map<Enums::LocationType, QString> locationTypeMap;
extern DECLSPEC std::map<Enums::MassType, QString> massTypeMap;
extern DECLSPEC std::map<Enums::MassToleranceType, QString>
  massToleranceTypeMap;
extern DECLSPEC std::map<Enums::PolymerEnd, QString> polymerEndMap;
extern DECLSPEC std::map<Enums::IonizationOutcome, QString>
  ionizationOutcomeMap;
extern DECLSPEC std::map<Enums::SelectionType, QString> selectionTypeMap;
extern DECLSPEC std::map<Enums::CapType, QString> capTypeMap;
extern DECLSPEC std::map<Enums::ChemicalEntity, QString> chemicalEntityMap;
extern DECLSPEC std::map<Enums::CrossLinkEncompassed, QString>
  crossLinkEncompassedMap;
extern DECLSPEC std::map<Enums::CleavageAction, QString> CleavageActionMap;
extern DECLSPEC std::map<Enums::FragEnd, QString> fragEndMap;
extern DECLSPEC std::map<Enums::ChemicalGroupTrapped, QString>
  chemicalGroupTrappedMap;
extern DECLSPEC std::map<Enums::ChemicalGroupFate, QString>
  chemicalGroupFateMap;
extern DECLSPEC std::map<Enums::MassPeakShapeType, QString>
  massPeakShapeTypeMap;
extern DECLSPEC std::map<Enums::MassPeakWidthLogic, QString>
  massPeakWidthLogicMap;
extern DECLSPEC std::map<Enums::MassDataType, QString> massDataTypeMap;


extern DECLSPEC int DEFAULT_DEC_PLACES;
extern DECLSPEC int ATOM_DEC_PLACES;
extern DECLSPEC int OLIGOMER_DEC_PLACES;
extern DECLSPEC int POLYMER_DEC_PLACES;
extern DECLSPEC int PKA_PH_PI_DEC_PLACES;
extern DECLSPEC int MZ_DEC_PLACES;
extern DECLSPEC int DELTA_MZ_DEC_PLACES;
extern DECLSPEC int RT_MINUTES_DEC_PLACES;
extern DECLSPEC int RT_SECONDS_DEC_PLACES;
extern DECLSPEC int INTENSITY_DEC_PLACES;

typedef QStringList ErrorList;


} // namespace libXpertMassCore
} // namespace MsXpS

Q_DECLARE_METATYPE(MsXpS::libXpertMassCore::ErrorList)
extern int errorListMetaTypeId;

Q_DECLARE_METATYPE(MsXpS::libXpertMassCore::ErrorList *);
extern int errorListPtrMetaTypeId;
