/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright (C) 2009--2020 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 <vector>


/////////////////////// Qt includes


/////////////////////// pappsomspp includes
#include <pappsomspp/core/msfile/msfileaccessor.h>


/////////////////////// libXpertMassCore includes
#include <MsXpS/libXpertMassCore/MonitoredTaskInterface.hpp>

/////////////////////// libXpertMassGui includes
// #include <MsXpS/libXpertMassGui/TaskMonitorCompositeWidget.hpp>


/////////////////////// Local includes

namespace MsXpS
{
namespace MineXpert
{

enum class IonMobilityUnit
{
  NONE,
  ONE_OVER_KO,
  SCAN,
  DT,
  LAST,
};

struct MsRunProbeInfo
{
  QString vendor;
  QString description;
  QString probeErrors;
  double retentionTimeBeginInSeconds;
  double retentionTimeEndInSeconds;
  IonMobilityUnit ionMobilityUnit;
  double ionMobilityScansBegin;
  double ionMobilityScansEnd;
  double ionMobilityOneOverKoBegin;
  double ionMobilityOneOverKoEnd;
  double ionMobilityDtBegin;
  double ionMobilityDtEnd;
  bool ionMobilityScansMergeRequired;
  std::vector<std::size_t> msLevels;
  std::size_t ms1SpectraCount;
  std::size_t ms2SpectraCount;
  int mzBinCount;
  double mzBegin        = -1;
  double mzEnd          = -1;
  int mzBinsMergeWindow = -1;

  // Constructors
  MsRunProbeInfo() {};

  MsRunProbeInfo(const MsRunProbeInfo &other)
  {
    vendor                        = other.vendor;
    description                   = other.description;
    probeErrors                   = other.probeErrors;
    retentionTimeBeginInSeconds   = other.retentionTimeBeginInSeconds;
    retentionTimeEndInSeconds     = other.retentionTimeEndInSeconds;
    ionMobilityUnit               = other.ionMobilityUnit;
    ionMobilityScansBegin         = other.ionMobilityScansBegin;
    ionMobilityScansEnd           = other.ionMobilityScansEnd;
    ionMobilityOneOverKoBegin     = other.ionMobilityOneOverKoBegin;
    ionMobilityOneOverKoEnd       = other.ionMobilityOneOverKoEnd;
    ionMobilityDtBegin            = other.ionMobilityDtBegin;
    ionMobilityDtEnd              = other.ionMobilityDtEnd;
    ionMobilityScansMergeRequired = other.ionMobilityScansMergeRequired;
    msLevels                      = other.msLevels;
    ms1SpectraCount               = other.ms1SpectraCount;
    ms2SpectraCount               = other.ms2SpectraCount;
    mzBinCount                    = other.mzBinCount;
    mzBegin                       = other.mzBegin;
    mzEnd                         = other.mzEnd;
    mzBinsMergeWindow             = other.mzBinsMergeWindow;
  }

  MsRunProbeInfo &
  operator=(const MsRunProbeInfo &other)
  {
    if(this == &other)
      return *this;

    vendor                        = other.vendor;
    description                   = other.description;
    probeErrors                   = other.probeErrors;
    retentionTimeBeginInSeconds   = other.retentionTimeBeginInSeconds;
    retentionTimeEndInSeconds     = other.retentionTimeEndInSeconds;
    ionMobilityUnit               = other.ionMobilityUnit;
    ionMobilityScansBegin         = other.ionMobilityScansBegin;
    ionMobilityScansEnd           = other.ionMobilityScansEnd;
    ionMobilityOneOverKoBegin     = other.ionMobilityOneOverKoBegin;
    ionMobilityOneOverKoEnd       = other.ionMobilityOneOverKoEnd;
    ionMobilityDtBegin            = other.ionMobilityDtBegin;
    ionMobilityDtEnd              = other.ionMobilityDtEnd;
    ionMobilityScansMergeRequired = other.ionMobilityScansMergeRequired;
    msLevels                      = other.msLevels;
    ms1SpectraCount               = other.ms1SpectraCount;
    ms2SpectraCount               = other.ms2SpectraCount;
    mzBinCount                    = other.mzBinCount;
    mzBegin                       = other.mzBegin;
    mzEnd                         = other.mzEnd;
    mzBinsMergeWindow             = other.mzBinsMergeWindow;

    return *this;
  }
};

typedef std::shared_ptr<MsRunProbeInfo> MsRunProbeInfoSPtr;


typedef std::vector<pappso::QualifiedMassSpectrumCstSPtr>
  QualifiedMassSpectraVector;

typedef std::shared_ptr<QualifiedMassSpectraVector>
  QualifiedMassSpectraVectorSPtr;

typedef std::shared_ptr<const QualifiedMassSpectraVector>
  QualifiedMassSpectraVectorCstSPtr;

class MsRunProber: public libXpertMassCore::MonitoredTaskInterface
{
  Q_OBJECT

  public:
  MsRunProber(pappso::MsFileAccessorSPtr ms_file_accessor_sp,
              QObject *parent = nullptr);

  virtual ~MsRunProber();

  pappso::MsFileAccessorSPtr getMsFileAccessorSPtr();

  void setReadMsRunFullyInMemory(bool is_full_in_memory);
  bool isReadMsRunFullyInMemory() const;

  bool shouldStop() const;

  virtual MsRunProbeInfo probe() = 0;

  public slots:

  virtual void cancelOperation();


  signals:

  void cancelOperationSignal();

  void setTaskDescriptionTextSignal(QString text);

  void setupProgressBarSignal(std::size_t min_value, std::size_t max_value);
  void setProgressBarMinValueSignal(std::size_t value);
  void setProgressBarMaxValueSignal(std::size_t value);
  void incrementProgressBarMaxValueSignal(std::size_t increment);
  void setProgressBarCurrentValueSignal(std::size_t number_of_processed_nodes);
  void incrementProgressBarCurrentValueSignal(std::size_t increment);

  void setStatusTextSignal(QString text);
  void appendStatusTextSignal(QString text);
  void setStatusTextAndCurrentValueSignal(QString text, int value);

  void
  incrementProgressBarCurrentValueAndSetStatusTextSignal(std::size_t increment,
                                                         const QString &text);
  void logTextToConsoleSignal(QString text);
  void logColoredTextToConsoleSignal(QString text, QColor color);

  void lockTaskMonitorCompositeWidgetSignal();
  void unlockTaskMonitorCompositeWidgetSignal();

  protected:
  pappso::MsFileAccessorSPtr msp_msFileAccessor;
  bool m_isOperationCancelled = false;
  bool m_isReadMsRunFullyInMemory;

  private:
};

typedef std::shared_ptr<MsRunProber> MsRunProberSPtr;

} // namespace MineXpert

} // namespace MsXpS


Q_DECLARE_METATYPE(MsXpS::MineXpert::MsRunProber)
extern int MsRunProberMetaTypeId;

Q_DECLARE_METATYPE(MsXpS::MineXpert::MsRunProberSPtr)
extern int MsRunProberSPtrMetaTypeId;
