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

#include <QSettings>
#include <QFileDialog>
#include <QMessageBox>
#include <QDebug>
#include <QCommandLineParser>
#include "../config.h"
#include "mainwindow.h"

#include "ui_main.h"
#include <pappsomspp/core/pappsoexception.h>
#include "../utils/utils.h"
#include "output/xpip.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::Main)
{
  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));
  // http://pappso.inra.fr/demande/ws/pappso_software/i2masschroq
  _p_app = QCoreApplication::instance();
  ui->setupUi(this);
  setWindowTitle(QString("%1 %2").arg(SOFTWARE_NAME).arg(i2MassChroQ_VERSION));
  setWindowIcon(QIcon(":/i2masschroq_icon/resources/i2MassChroQ_icon.svg"));
  


  _p_app->setOrganizationName("PAPPSO");
  _p_app->setOrganizationDomain("pappso.inrae.fr");
  _p_app->setApplicationName("i2masschroq");
  _p_app->setApplicationVersion(i2MassChroQ_VERSION);

  mp_worker = new WorkerThread(this);
  mp_worker->moveToThread(&_worker_thread);
  _worker_thread.start();

  _p_load_results_dialog       = new LoadResultsDialog(this);
  _p_export_spreadsheet_dialog = new ExportSpreadsheetDialog(this);
  _p_waiting_message_dialog    = new WaitingMessageDialog(this);


  _project_window = new ProjectWindow(this);

  ui->menu_export_files->setDisabled(true);
  ui->actionSpectral_Count->setDisabled(true);
  ui->actionMassChroQ->setDisabled(true);
  ui->actionMCQR->setVisible(true);
  ui->centralwidget->layout()->addWidget(_project_window);
  _project_window->hide();
  ui->action_save_project->setDisabled(true);
  ui->default_display_widget->show();
  //_protein_list_window = new ProteinListWindow(this);
  // QDockWidget *dock = new QDockWidget(tr("Protein List"), this);
  // dock->setWidget(_protein_list_window);
  // addDockWidget(Qt::RightDockWidgetArea, dock);

  qRegisterMetaType<ProjectSp>("ProjectSp");
  qRegisterMetaType<MasschroqFileParametersSp>("MasschroqFileParametersSp");
  qRegisterMetaType<AutomaticFilterParameters>("AutomaticFilterParameters");
  qRegisterMetaType<GroupingType>("GroupingType");


  // ui->actionSpectral_Count->setVisible(false);
#if EXPERIMENTAL_FEATURES_ON == 1
  // ui->menuMCQR_dev->setVisible(false);
  // ui->actionSpectral_Count->setVisible(true);
#endif

#if QT_VERSION >= 0x050000
  // Qt5 code
  connect(_p_load_results_dialog,
          &LoadResultsDialog::accepted,
          this,
          &MainWindow::doAcceptedLoadResultDialog);
  connect(_p_export_spreadsheet_dialog,
          &ExportSpreadsheetDialog::accepted,
          this,
          &MainWindow::doAcceptedExportSpreadsheetDialog);
  connect(&m_onlineVersion,
          &HttpVersion::httpVersionReady,
          this,
          &MainWindow::doCheckNewVersion);
  connect(this,
          &MainWindow::operateFreeAllMsRunReaders,
          _project_window,
          &ProjectWindow::doCleanMsRunReaders);
#else
#endif
}

MainWindow::~MainWindow()
{
  qDebug();
  _worker_thread.quit();
  _worker_thread.wait();
  // if (_p_ms_data_file != nullptr) delete _p_ms_data_file;
  delete ui;
  // delete _project_window;
  delete _p_load_results_dialog;
  delete _p_export_spreadsheet_dialog;
  delete _p_waiting_message_dialog;
  if(_p_export_masschroq_dialog != nullptr)
    {
      delete _p_export_masschroq_dialog;
    }

  if(mp_msstatsRun != nullptr)
    {
      mp_msstatsRun->close();
      delete mp_msstatsRun;
    }
  if(mp_mcqrRun != nullptr)
    {

      mp_mcqrRun->close();
      delete mp_mcqrRun;
    }
  if(mp_mcqrScRun != nullptr)
    {
      mp_mcqrScRun->close();
      delete mp_mcqrScRun;
    }
  if(mp_sageRunDialog != nullptr)
    {
      mp_sageRunDialog->close();
      delete mp_sageRunDialog;
    }
  qDebug();
}

const ProjectSp &
MainWindow::getProjectSp() const
{
  return _project_sp;
}

bool
MainWindow::stopWorkerThread()
{
  qDebug();
  QMutexLocker mutex_locker(&m_mutex);
  if(_p_waiting_message_dialog != nullptr)
    {
      return _p_waiting_message_dialog->stopWorkerThread();
    }
  else
    {
      return false;
    }
}

void
MainWindow::closeEvent(QCloseEvent *event)
{
  if(mp_msstatsRun != nullptr)
    {
      mp_msstatsRun->close();
    }
  if(_project_sp != nullptr)
    {
      if(_project_sp.get()->getProjectChangedStatus() == true)
        {
          event->ignore();
          int ret = chooseSaveMssgBox();

          switch(ret)
            {
              case 0: // == DestructiveRole
                event->accept();
                break;
              case 1: // == RejectRole
                event->ignore();
                break;
              case 2: // == AcceptRole
                doActionSaveProject();
                event->accept();
                break;
              default:
                break;
            }
        }
      else
        {
          event->accept();
        }
    }
  else
    {
      event->accept();
    }
}

void
MainWindow::viewError(QString error)
{
  hideWaitingMessage();
  QMessageBox::warning(
    this, tr("Oops! an error occurred in i2MassChroQ. Don't panic :"), error);
}

void
MainWindow::doDisplayJobFinished(QString message)
{
  qDebug() << message;
  hideWaitingMessage();
  QMessageBox::information(this, tr("job finished"), message);
}

void
MainWindow::doDisplayJobCanceled(QString message)
{
  hideWaitingMessage();
  QMessageBox::warning(this, tr("job canceled"), message);
}

void
MainWindow::doDisplayLoadingMessage(QString message)
{
  qDebug() << message;
  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->message(message);
  ui->statusbar->showMessage(message);
}

void
MainWindow::doDisplayLoadingMessagePercent(QString message, int value)
{
  qDebug() << message << " " << value;
  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->message(message, value);
  ui->statusbar->showMessage(message);
}

void
MainWindow::doDisplayLoadingPercent(int value)
{
  qDebug() << value;
  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->percent(value);
}

void
MainWindow::doWorkerSetText(QString text)
{
  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->setText(text);
}
void
MainWindow::doWorkerAppendText(const char *text)
{
  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->appendText(text);
}

void
MainWindow::doWorkerAppendQString(QString message)
{
  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->appendText(message);
}

void
MainWindow::doActionQuit()
{
  qDebug();
  this->close();
}

void
MainWindow::doAcceptedExportSpreadsheetDialog()
{
  qDebug();
  try
    {
      QString format = this->_p_export_spreadsheet_dialog->getExportFormat();
      QSettings settings;
      QString default_location =
        settings.value("path/export_ods", "").toString();

      QString filename;
      if(format == "ods")
        {
          filename = QFileDialog::getSaveFileName(
            this,
            tr("Save ODS file"),
            QString("%1/%2.ods")
              .arg(default_location)
              .arg(_project_sp.get()->getProjectName()),
            tr("Open Document Spreadsheet (*.ods)"));

          settings.setValue("path/export_ods",
                            QFileInfo(filename).absolutePath());
        }
      else
        {
          filename = QFileDialog::getExistingDirectory(
            this, tr("Save TSV files"), QString("%1").arg(default_location));

          if(!filename.isEmpty() && !filename.isNull())
            {
              QDir parent(filename);
              settings.setValue("path/export_ods", parent.canonicalPath());
              qDebug() << parent.absolutePath();

              if(parent.mkdir(_project_sp.get()->getProjectName()))
                {
                  parent.cd(_project_sp.get()->getProjectName());
                  filename = parent.canonicalPath();
                }
              else
                {
                  if(parent.cd(_project_sp.get()->getProjectName()))
                    {
                      throw pappso::PappsoException(
                        QObject::tr(
                          "Unable to write files : export directory %1 "
                          "already exists")
                          .arg(parent.canonicalPath()));
                    }
                  throw pappso::PappsoException(
                    QObject::tr("Unable to create directory %1/%2. Check file "
                                "system permissions")
                      .arg(parent.canonicalPath())
                      .arg(_project_sp.get()->getProjectName()));
                }
            }
        }
      if(filename.isEmpty())
        {
          return;
        }


      showWaitingMessage(
        tr("writing %1 ODS file").arg(QFileInfo(filename).fileName()));
      emit operateWritingOdsFile(
        filename, format, _project_sp, _p_export_spreadsheet_dialog);
      // emit operateXpipFile(filename);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error while writing ODS file :\n%1").arg(error.qwhat()));
    }

  qDebug();
}

void
MainWindow::doAcceptedTandemRunDialog()
{
  qDebug();
  showWaitingMessage(tr("Running X!Tandem"));
  qDebug();
  emit operateRunningXtandem(_p_tandem_run_dialog->getTandemRunBatch());
  qDebug();
}

void
MainWindow::doAcceptedSageRunDialog()
{
  qDebug();
  showWaitingMessage(tr("Running Sage"));
  qDebug();
  emit operateRunningSage(mp_sageRunDialog->getSageRunBatch());
  qDebug();
}


void
MainWindow::doAcceptedLoadResultDialog()
{
  qDebug();
  AutomaticFilterParameters param =
    _p_load_results_dialog->getAutomaticFilterParameters();
  QSettings settings;
  settings.setValue(
    "automatic_filter/cross_sample",
    QString("%1").arg(param.getFilterCrossSamplePeptideNumber()));
  settings.setValue("automatic_filter/peptide_number",
                    QString("%1").arg(param.getFilterMinimumPeptidePerMatch()));
  settings.setValue("automatic_filter/peptide_evalue",
                    QString("%1").arg(param.getFilterPeptideEvalue()));
  settings.setValue("automatic_filter/protein_evalue",
                    QString("%1").arg(param.getFilterProteinEvalue()));

  QStringList file_list = _p_load_results_dialog->getFileList();
  bool is_individual    = _p_load_results_dialog->isIndividual();

  showWaitingMessage(tr("Loading files"));
  emit operateLoadingResults(is_individual, param, file_list);
  qDebug();
}

void
MainWindow::doOperationFailed(QString error)
{
  hideWaitingMessage();
  viewError(error);
}
void
MainWindow::doOperationFinished()
{
  hideWaitingMessage();
}
void
MainWindow::doGroupingFinished()
{
  hideWaitingMessage();
  _project_window->setProjectSp(_project_sp);
}
void
MainWindow::doLoadingResultsReady(ProjectSp project_sp)
{
  qDebug();
  if(_p_load_results_dialog != nullptr)
    {
      //_p_load_results_dialog->setProjectContaminants(project_sp.get());
    }
  doProjectReady(project_sp);
  qDebug();
}

void
MainWindow::doProjectReady(ProjectSp project_sp)
{
  _project_sp = project_sp;
  qDebug() << _project_sp.get()->getFastaFileStore().getFastaFileList().size();

  showWaitingMessage(tr("grouping proteins"));
  emit operateGrouping(project_sp);

  ui->menu_export_files->setDisabled(false);
  ui->actionMassChroQ->setDisabled(false);
  ui->actionModifications->setDisabled(false);
  ui->actionLabeling_methods->setDisabled(false);
  ui->actionSpectral_Count->setDisabled(false);

  // Create the alignment group with all the msrun within
  if(_project_sp->getAllMsRunAlignmentGroup() == nullptr)
    {
      std::shared_ptr<MsRunAlignmentGroup> all_msrun_group =
        std::make_shared<MsRunAlignmentGroup>(_project_sp.get(), "All_samples");
      for(MsRunSp ms_run_sp : _project_sp->getMsRunStore().getMsRunList())
        {
          all_msrun_group->addMsRunToMsRunAlignmentGroupList(ms_run_sp);
        }
      _project_sp->setAllMsRunAlignmentGroup(all_msrun_group);
    }

  // Reset masschroq_run_dialog with new project
  if(_p_export_masschroq_dialog != nullptr)
    {
      delete _p_export_masschroq_dialog;
      _p_export_masschroq_dialog = nullptr;
    }

  _project_window->show();
  showProjectName();

  ui->default_display_widget->hide();
  ui->action_save_project->setDisabled(false);
  qDebug() << "end";
}

void
MainWindow::doActionLabelingMethods()
{
  _project_window->editLabelingMethods();
}

void
MainWindow::doActionDeepProtStudio()
{
  _project_window->deepProtPostProcessInterface();
}

void
MainWindow::doActionModifications()
{
  _project_window->editModifications();
}

void
MainWindow::doProjectNotReady(QString error)
{
  hideWaitingMessage();
  viewError(error);
  hideWaitingMessage();
}


void
MainWindow::doActionTandemRun()
{
  try
    {
      if(_p_tandem_run_dialog == nullptr)
        {
          _p_tandem_run_dialog = new TandemRunDialog(this);
          connect(_p_tandem_run_dialog,
                  &TandemRunDialog::accepted,
                  this,
                  &MainWindow::doAcceptedTandemRunDialog);
        }
      _p_tandem_run_dialog->show();
      _p_tandem_run_dialog->raise();
      _p_tandem_run_dialog->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error opening X!Tandem run dialog window :\n%1")
                  .arg(error.qwhat()));
    }
}

void
MainWindow::doActionSageRun()
{
  try
    {
      if(mp_sageRunDialog == nullptr)
        {
          mp_sageRunDialog = new SageRunDialog(this);
          connect(mp_sageRunDialog,
                  &SageRunDialog::accepted,
                  this,
                  &MainWindow::doAcceptedSageRunDialog);
        }
      mp_sageRunDialog->show();
      mp_sageRunDialog->raise();
      mp_sageRunDialog->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error opening Sage run dialog window :\n%1").arg(error.qwhat()));
    }
}


void
MainWindow::loadResults()
{

  _p_load_results_dialog->show();
  _p_load_results_dialog->raise();
  _p_load_results_dialog->activateWindow();
}

void
MainWindow::hideWaitingMessage()
{

  QMutexLocker mutex_locker(&m_mutex);
  _p_waiting_message_dialog->hide();
  ui->statusbar->showMessage("");
}

void
MainWindow::showWaitingMessage(const QString title)
{
  QMutexLocker mutex_locker(&m_mutex);
  qDebug();
  _p_waiting_message_dialog->setWindowTitle(title);
  qDebug();
  _p_waiting_message_dialog->message("");
  _p_waiting_message_dialog->show();
  qDebug();
  _p_waiting_message_dialog->raise();
  _p_waiting_message_dialog->activateWindow();
  qDebug();
}

void
MainWindow::selectXpipFile()
{
  try
    {
      QSettings settings;
      QString default_location = settings.value("path/xpipfile", "").toString();

      QString filename =
        QFileDialog::getOpenFileName(this,
                                     tr("Open XPIP File"),
                                     default_location,
                                     tr("xpip files (*.xpip);;all files (*)"));

      if(filename.isEmpty())
        {
          return;
        }

      settings.setValue("path/xpipfile", QFileInfo(filename).absolutePath());
      showWaitingMessage(
        tr("Loading %1 XPIP file").arg(QFileInfo(filename).fileName()));
      emit operateXpipFile(filename);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error while reading XPIP file :\n%1").arg(error.qwhat()));
    }
}


void
MainWindow::doActionSaveProject()
{
  try
    {
      // QMessageBox::warning(this,
      //                     tr("Experimental feature"), "WARNING : project
      //                     files export is not ready");
      QSettings settings;
      QString default_location = settings.value("path/xpipfile", "").toString();

      if(_project_window != nullptr)
        {
          _project_sp.get()->setProjectName(_project_window->getProjectName());
        }

      QString filename = QFileDialog::getSaveFileName(
        this,
        tr("Save XPIP file"),
        QString("%1/%2.xpip")
          .arg(default_location)
          .arg(_project_sp.get()->getProjectName()),
        tr("XPIP (*.xpip)"));

      if(filename.isEmpty())
        {
          return;
        }

      settings.setValue("path/xpipfile", QFileInfo(filename).absolutePath());
      showWaitingMessage(
        tr("Writing %1 XPIP file").arg(QFileInfo(filename).fileName()));
      emit operateWritingXpipFile(filename, _project_sp);
      _project_sp.get()->setProjectName(filename);
      showProjectName();
      _project_sp->setProjectChangedStatus(false);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error while writing XPIP file :\n%1").arg(error.qwhat()));
    }
}

void
MainWindow::doActionFann()
{
  qDebug();
  try
    {
      QSettings settings;
      QString default_location = settings.value("path/fann", "").toString();

      QString filename = QFileDialog::getSaveFileName(
        this,
        tr("Save Fann data file"),
        QString("%1/untitled.data").arg(default_location),
        tr("data (*.data)"));

      if(filename.isEmpty())
        {
          return;
        }

      settings.setValue("path/fann", QFileInfo(filename).absolutePath());

      showWaitingMessage(
        tr("Writing %1 Fann data file").arg(QFileInfo(filename).fileName()));
      emit operateWritingFannDataFile(filename, _project_sp);
      // emit operateXpipFile(filename);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error while writing Fann data file :\n%1").arg(error.qwhat()));
    }
  qDebug();
}

void
MainWindow::doActionMcqrSpectralCount()
{
  qDebug();

  try
    {
      if(mp_mcqrScRun == nullptr)
        {
          mp_mcqrScRun = new McqrScRunView(this);
        }
      mp_mcqrScRun->show();
      mp_mcqrScRun->raise();
      mp_mcqrScRun->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error opening MCQR spectral count run dialog window :\n%1")
                  .arg(error.qwhat()));
    }
}

void
MainWindow::doActionMcqrDev()
{
  qDebug();

  try
    {
      if(mp_mcqrRun == nullptr)
        {
          mp_mcqrRun = new McqrRunViewNg(this);
        }
      mp_mcqrRun->show();
      mp_mcqrRun->raise();
      mp_mcqrRun->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error opening MCQR run dialog window :\n%1").arg(error.qwhat()));
    }
}

void
MainWindow::doActionMsStats()
{
  qDebug();

  try
    {
      if(mp_msstatsRun == nullptr)
        {
          mp_msstatsRun = new MsStatsRunView(this);
        }
      mp_msstatsRun->show();
      mp_msstatsRun->raise();
      mp_msstatsRun->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error opening MSstats run dialog window :\n%1").arg(error.qwhat()));
    }
}


void
MainWindow::doActionSpreadsheet()
{
  qDebug();
  try
    {
      if(_project_sp.get() != nullptr)
        {
          _p_export_spreadsheet_dialog->setProject(_project_sp.get());
        }
      _p_export_spreadsheet_dialog->show();
      _p_export_spreadsheet_dialog->raise();
      _p_export_spreadsheet_dialog->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error doActionSpreadsheet :\n%1").arg(error.qwhat()));
    }
  qDebug();
}

void
MainWindow::doActionFasta()
{
  QSettings settings;
  QString default_location = settings.value("path/fastafile", "").toString();

  QString filename =
    QFileDialog::getSaveFileName(this,
                                 tr("Save FASTA file"),
                                 QString("%1/%2.fasta")
                                   .arg(default_location)
                                   .arg(_project_sp.get()->getProjectName()),
                                 tr("FASTA (*.fasta)"));

  if(filename.isEmpty())
    {
      return;
    }

  settings.setValue("path/fastafile", QFileInfo(filename).absolutePath());

  showWaitingMessage(
    tr("Writing %1 FASTA file").arg(QFileInfo(filename).fileName()));
  emit operateWritingFastaFile(filename, _project_sp, ExportFastaType::all);
}


void
MainWindow::doActionFastaAllValidTargetProteins()
{
  QSettings settings;
  QString default_location = settings.value("path/fastafile", "").toString();

  QString filename =
    QFileDialog::getSaveFileName(this,
                                 tr("Save FASTA file"),
                                 QString("%1/%2.fasta")
                                   .arg(default_location)
                                   .arg(_project_sp.get()->getProjectName()),
                                 tr("FASTA (*.fasta)"));

  if(filename.isEmpty())
    {
      return;
    }

  settings.setValue("path/fastafile", QFileInfo(filename).absolutePath());

  showWaitingMessage(
    tr("Writing %1 FASTA file").arg(QFileInfo(filename).fileName()));
  emit operateWritingFastaFile(
    filename, _project_sp, ExportFastaType::allValidTargetProteins);
}

void
MainWindow::doActionFastaOneBySubgroup()
{
  QSettings settings;
  QString default_location = settings.value("path/fastafile", "").toString();

  QString filename =
    QFileDialog::getSaveFileName(this,
                                 tr("Save FASTA file"),
                                 QString("%1/%2.fasta")
                                   .arg(default_location)
                                   .arg(_project_sp.get()->getProjectName()),
                                 tr("FASTA (*.fasta)"));

  if(filename.isEmpty())
    {
      return;
    }

  settings.setValue("path/fastafile", QFileInfo(filename).absolutePath());

  showWaitingMessage(
    tr("Writing %1 FASTA file").arg(QFileInfo(filename).fileName()));
  emit operateWritingFastaFile(
    filename, _project_sp, ExportFastaType::oneBySubgroup);
}

void
MainWindow::doActionFastaOneByGroup()
{
  QSettings settings;
  QString default_location = settings.value("path/fastafile", "").toString();

  QString filename =
    QFileDialog::getSaveFileName(this,
                                 tr("Save FASTA file"),
                                 QString("%1/%2.fasta")
                                   .arg(default_location)
                                   .arg(_project_sp.get()->getProjectName()),
                                 tr("FASTA (*.fasta)"));

  if(filename.isEmpty())
    {
      return;
    }

  settings.setValue("path/fastafile", QFileInfo(filename).absolutePath());

  showWaitingMessage(
    tr("Writing %1 FASTA file").arg(QFileInfo(filename).fileName()));
  emit operateWritingFastaFile(
    filename, _project_sp, ExportFastaType::oneByGroup);
}


void
MainWindow::doActionMassChroQ()
{
  qDebug();

  try
    {
      _project_sp.get()->checkPsimodCompliance();
      if(_p_export_masschroq_dialog == nullptr)
        {
          _p_export_masschroq_dialog = new MassChroqRunDialog(this, mp_worker);
        }

      if(_project_sp.get() != nullptr)
        {
          _p_export_masschroq_dialog->setProjectSPtr(this->_project_sp);
          _p_export_masschroq_dialog->setAlignmentGroups();
          _p_export_masschroq_dialog->setMasschroqFileParameters();
        }
      _p_export_masschroq_dialog->show();
      _p_export_masschroq_dialog->raise();
      _p_export_masschroq_dialog->activateWindow();
    }
  catch(pappso::PappsoException &error)
    {
      viewError(tr("Error doActionMassChroQ :\n%1").arg(error.qwhat()));
    }
  qDebug();
}


void
MainWindow::doActionOneGroupMcqr(QAction *action_group)
{
  if(action_group != nullptr)
    {
      QMessageBox message_box;
      message_box.setWindowTitle(tr("Work in progress"));
      message_box.setIcon(QMessageBox::Information);
      message_box.setText(tr("The MCQR analysis of one group only such as %1 "
                             "is not implemented yet!")
                            .arg(action_group->text()));
      message_box.exec();
    }
}

void
MainWindow::doAcceptedMassChroqRunDialog()
{
  qDebug();
  try
    {

      _project_sp.get()->getMasschroqFileParametersSp().get()->save();
      qDebug() << _project_sp.get()
                    ->getMasschroqFileParametersSp()
                    .get()
                    ->alignment_groups.size();
      QSettings settings;
      QString default_location = settings.value("path/mcqfile", "").toString();

      QString filename =
        QFileDialog::getSaveFileName(this,
                                     tr("Save MassChroq JSON file"),
                                     tr("%1/%2.json")
                                       .arg(default_location)
                                       .arg(_project_sp->getProjectName()),
                                     tr("MassChroQ JSON (*.json)"));

      if(filename.isEmpty())
        {
          return;
        }

      settings.setValue("path/mcqfile", QFileInfo(filename).absolutePath());

      showWaitingMessage(
        tr("Writing %1 MassChroqML file").arg(QFileInfo(filename).fileName()));
      emit operateWritingMassChroqFile(filename, _project_sp);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error while writing MassChroqML file :\n%1").arg(error.qwhat()));
    }

  qDebug();
}


void
MainWindow::doWritingMassChroQmlFileFinished(
  QString masschroqml_file,
  std::vector<MsRunAlignmentGroupSp> quantified_groups [[maybe_unused]])
{
  qDebug() << "MassChroQml created";
  if(_p_export_masschroq_dialog->getMassChroqRunStatus())
    {
      _p_export_masschroq_dialog->setMassChroqRunBatchParam(masschroqml_file);
      showWaitingMessage(tr("Running MassChroQ"));
      emit operateRunningMassChroq(
        _p_export_masschroq_dialog->getMassChroqRunBatchParam());
    }
  _p_export_masschroq_dialog->updateAlignmentGroupsStatus(masschroqml_file);
  _project_window->projectStatusChanged();
}

void
MainWindow::doActionMassChroqPRM()
{
  qDebug();
  try
    {
      _project_sp.get()->checkPsimodCompliance();

      QSettings settings;
      QString default_location =
        settings.value("path/mcqprmfile", "").toString();

      QString filename = QFileDialog::getSaveFileName(
        this,
        tr("Save MassChroqPRM file"),
        QString("%1/%2.masschroqprm")
          .arg(default_location)
          .arg(_project_sp.get()->getProjectName()),
        tr("MassChroqPRM (*.masschroqprm)"));

      if(filename.isEmpty())
        {
          return;
        }

      settings.setValue("path/mcqprmfile", QFileInfo(filename).absolutePath());

      showWaitingMessage(
        tr("Writing %1 MassChroqPRM file").arg(QFileInfo(filename).fileName()));
      emit operateWritingMassChroqPrmFile(filename, _project_sp);
      // emit operateXpipFile(filename);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error while writing MassChroqML file :\n%1").arg(error.qwhat()));
    }
  qDebug();
}

void
MainWindow::doActionProticDb()
{
  qDebug();
  try
    {
      _project_sp.get()->checkPsimodCompliance();

      QSettings settings;
      QString default_location =
        settings.value("path/proticfile", "").toString();

      QString filename = QFileDialog::getSaveFileName(
        this,
        tr("Save PROTICdbML file"),
        QString("%1/%2.proticdbml")
          .arg(default_location)
          .arg(_project_sp.get()->getProjectName()),
        tr("PROTICdbML (*.proticdbml)"));

      if(filename.isEmpty())
        {
          return;
        }

      settings.setValue("path/proticfile", QFileInfo(filename).absolutePath());

      showWaitingMessage(
        tr("Writing %1 PROTICdbML file").arg(QFileInfo(filename).fileName()));
      emit operateWritingProticFile(filename, _project_sp);
      // emit operateXpipFile(filename);
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("Error while writing PROTICdbML file :\n%1").arg(error.qwhat()));
    }
  qDebug();
}

void
MainWindow::doActionAbout()
{
  qDebug();
  if(_p_about_dialog == nullptr)
    {
      _p_about_dialog = new AboutDialog(this);
    }
  _p_about_dialog->show();
  _p_about_dialog->raise();
  _p_about_dialog->activateWindow();

  qDebug();
}

void
MainWindow::doActionSettings()
{
  qDebug();
  if(_p_edit_settings == nullptr)
    {
      _p_edit_settings = new EditSettings(this);
    }
  _p_edit_settings->show();
  _p_edit_settings->raise();
  _p_edit_settings->activateWindow();

  qDebug();
}

void
MainWindow::doCheckNewVersion()
{
  qDebug();
  if(m_onlineVersion.isNewVersion())
    {
      hideWaitingMessage();
      QMessageBox *version_message_box = new QMessageBox(this);
      version_message_box->setWindowTitle(tr("new version available"));
      version_message_box->setText(
        tr("A new %1 version is available %2\nCheck our web site \n"
           "%3\n to download it")
          .arg(SOFTWARE_NAME)
          .arg(m_onlineVersion.getVersion())
          .arg(m_onlineVersion.getPermalink()));
      QPushButton *download_button = version_message_box->addButton(
        tr("Download version %1").arg(m_onlineVersion.getVersion()),
        QMessageBox::AcceptRole);
      version_message_box->addButton(
        tr("Keep version %1").arg(QStringLiteral(i2MassChroQ_VERSION)),
        QMessageBox::RejectRole);

      version_message_box->exec();
      if(version_message_box->clickedButton() == download_button)
        {
          QDesktopServices::openUrl(QUrl(m_onlineVersion.getPermalink()));
        }
    }

  qDebug();
}


// 10ms after the application starts this method will run
// all QT messaging is running at this point so threads, signals and slots
// will all work as expected.
void
MainWindow::run()
{

  QTextStream errorStream(stderr, QIODevice::WriteOnly);

  try
    {
      qWarning() << qApp->applicationDirPath();
      QCommandLineParser parser;

      // throw pappso::PappsoException("test");
      parser.setApplicationDescription(
        QString(SOFTWARE_NAME).append(" ").append(i2MassChroQ_VERSION));
      parser.addHelpOption();
      parser.addVersionOption();
      parser.addPositionalArgument(
        "XPIP project file",
        QCoreApplication::translate("main", "Project file to open."));

      qDebug();

      // Process the actual command line arguments given by the user
      parser.process(*_p_app);


      QStringList xpip_list = parser.positionalArguments();
      if(xpip_list.size() > 0)
        {
          showWaitingMessage(tr("Loading %1 XPIP file").arg(xpip_list.at(0)));
          emit operateXpipFile(xpip_list.at(0));
        }
    }
  catch(pappso::PappsoException &error)
    {
      viewError(
        tr("An error occurred in i2MassChroQ. Error :\n%1").arg(error.qwhat()));
    }

  catch(std::exception &error)
    {
      viewError(
        tr("An error occurred in i2MassChroQ. Error :\n%1").arg(error.what()));
    }
}

void
MainWindow::showProjectName()
{
  if(_project_sp.get() != nullptr)
    {
      QString project_name = _project_sp.get()->getProjectName();
      setWindowTitle(QString("%1 - %2 %3")
                       .arg(project_name)
                       .arg(SOFTWARE_NAME)
                       .arg(i2MassChroQ_VERSION));
      emit projectNameChanged(project_name);
    }
}

int
MainWindow::chooseSaveMssgBox()
{
  QMessageBox save_box;
  save_box.setIcon(QMessageBox::Warning);
  save_box.setWindowTitle(
    QString("Save %1 Project?").arg(_project_sp.get()->getProjectName()));
  save_box.setText("The project has been modified.");
  save_box.setInformativeText("Do you want to save your changes?");
  save_box.addButton(
    new QPushButton(QIcon(":/icons/resources/icons/mit/ionicons/trash-bin"),
                    tr("Close without saving")),
    QMessageBox::DestructiveRole);
  save_box.addButton(
    new QPushButton(QIcon(":/icons/resources/icons/apache/unicons/cancel"),
                    tr("&Cancel")),
    QMessageBox::RejectRole);
  save_box.addButton(
    new QPushButton(QIcon(":/icons/resources/icons/apache/firefox/floppydisk2"),
                    tr("&Save")),
    QMessageBox::AcceptRole);
  //   save_box.setStandardButtons(QMessageBox::Save | QMessageBox::Discard |
  //                               QMessageBox::Cancel);
  //   save_box.setDefaultButton(QMessageBox::Save);
  int ret = save_box.exec();
  qDebug() << ret;
  return ret;
}

WorkerThread *
MainWindow::getWorkerThread()
{
  return mp_worker;
}

void
MainWindow::doFreeAllMsRunReaders()
{
  emit operateFreeAllMsRunReaders();
}

void
MainWindow::enableDeepProtStudio(bool enabled)
{
  ui->actionDeepProt_studio->setEnabled(enabled);
}

void
MainWindow::doShowStopButton()
{
  _p_waiting_message_dialog->showStopButton();
}
