
/*******************************************************************************
 * Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.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/>.
 *
 ******************************************************************************/

#include "projectwindow.h"
#include "ui_project_view.h"
#include "../mainwindow.h"
#include "gui/lists/peptide_list_view/peptidelistwindow.h"
#include "gui/lists/protein_list_view/proteinlistwindow.h"
#include "gui/project_view/identification_group_widget/identificationgroupwidget.h"
#include <QDebug>
#include <QApplication>
#include <QGridLayout>
#include <QMessageBox>
#include <pappsomspp/core/pappsoexception.h>
#include <numeric>
#include "../workerthread.h"
#include "../../core/labeling/labelingmethod.h"
#include "../../utils/utils.h"
#include <qcustomplot.h>
#include "gui/lists/ms_identification_run_list_view/msidentificationlistwindow.h"
#include "gui/lists/ms_identification_run_list_view/engine_detail_view/enginedetailwindow.h"
#include "../../core/qvalue/computeqvalues.h"

ProjectWindow::ProjectWindow(MainWindow *parent)
  : QMainWindow(parent), ui(new Ui::ProjectView)
{
  mp_mainWindow = parent;

  ui->setupUi(this);
  //   WorkerThread *p_worker = new WorkerThread(this);
  //   p_worker->moveToThread(&_worker_thread);
  //   _worker_thread.start();

  _p_edit_modifications     = new EditModifications(this);
  _p_edit_label_methods     = new EditLabelMethods(this);
  _p_waiting_message_dialog = new WaitingMessageDialog(this);


  ui->mass_histogram_widget->xAxis->setLabel("mass delta");
  ui->mass_histogram_widget->yAxis->setLabel("count");
  ui->mass_histogram_widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
  ui->mass_histogram_widget->axisRects().at(0)->setRangeDrag(Qt::Horizontal);
  ui->mass_histogram_widget->axisRects().at(0)->setRangeZoom(Qt::Horizontal);
  // legend->setVisible(false);
  ui->mass_histogram_widget->legend->setFont(QFont("Helvetica", 9));
  // set locale to english, so we get english decimal separator:
  // setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom));
  setFocusPolicy(Qt::ClickFocus);

  QCPGraph *p_graph = ui->mass_histogram_widget->addGraph();
  // p_graph->setName("raw xic");
  // QPen pen;
  // pen.setColor(getNewColors());
  // graph()->setPen(pen);
  // graph()->setName(lineNames.at(i-QCPGraph::lsNone));
  p_graph->setLineStyle(QCPGraph::LineStyle::lsStepCenter);
  // p_graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 2.0));

  QVBoxLayout *p_layout = new QVBoxLayout();
  ui->identifications_widget->setLayout(p_layout);

  ui->apply_filter_button->setEnabled(false);

  connect(ui->filter_parameter_widget,
          &AutomaticFilterWidget::automaticFilterParametersChanged,
          this,
          &ProjectWindow::doAutomaticFilterParametersChanged);
  connect(ui->contaminant_widget,
          &ContaminantWidget::changed,
          this,
          &ProjectWindow::doContaminantSelectionChanged);
  connect(ui->decoy_widget,
          &DecoyWidget::changed,
          this,
          &ProjectWindow::doDecoySelectionChanged);
  connect(_p_edit_label_methods,
          &EditLabelMethods::accepted,
          this,
          &ProjectWindow::doAcceptedLabelingMethod);
  connect(mp_mainWindow,
          &MainWindow::projectNameChanged,
          this,
          &ProjectWindow::doProjectNameChanged);
  connect(this,
          &ProjectWindow::projectStatusChanged,
          this,
          &ProjectWindow::doProjectStatusChanged);
  connect(mp_mainWindow->getWorkerThread(),
          &WorkerThread::bestMsrunForAlignmentGroupFinished,
          this,
          &ProjectWindow::doBestMsRunForAlignmentFinished);
  connect(this,
          &ProjectWindow::operateMassChroqExportDialog,
          mp_mainWindow,
          &MainWindow::doActionMassChroQ);

  connect(mp_mainWindow->getWorkerThread(),
          &WorkerThread::tiddResultText,
          this,
          &ProjectWindow::receiveTiddResults);
  //
  // grouping
  /*
  connect(this,
          &ProjectWindow::operateGrouping,
          main_window->getWorkerThread(),
          &WorkerThread::doGrouping);
          */
  mp_mainWindow->getWorkerThread()->connectProjectWindow(this);

  this->setDisabled(true);
}

ProjectWindow::~ProjectWindow()
{
  qDebug();

  // if (_p_ms_data_file != nullptr) delete _p_ms_data_file;
  //   _worker_thread.quit();
  //   _worker_thread.wait();
  qDebug();
  delete ui;
  qDebug();
  delete _p_edit_modifications;
  qDebug();
  delete _p_edit_label_methods;
  qDebug();
  delete _p_waiting_message_dialog;
  qDebug();


  if(mpa_deepProtGui != nullptr)
    {
      delete mpa_deepProtGui;
    }
}

Project *
ProjectWindow::getProjectP()
{
  return msp_project.get();
}

ProjectSp
ProjectWindow::getProjectSP()
{
  return msp_project;
}

void
ProjectWindow::setDefaultProteinListWindow(
  ProteinListWindow *p_protein_list_window)
{
  qDebug();
  _p_current_protein_list_window = p_protein_list_window;
  qDebug();
}

void
ProjectWindow::connectNewPtmIslandListWindow()
{
  qDebug();
  _p_current_ptm_island_list_window = new PtmIslandListWindow(this);
  _ptm_island_list_window_collection.push_back(
    _p_current_ptm_island_list_window);
  qDebug();
}
void
ProjectWindow::connectNewProteinListWindow()
{
  qDebug();
  _p_current_protein_list_window = new ProteinListWindow(this);

  _protein_list_window_collection.push_back(_p_current_protein_list_window);

  qDebug();
}

void
ProjectWindow::connectNewProteinDetailWindow()
{
  qDebug();
  _p_current_protein_detail_window = new ProteinWindow(this);
  _protein_detail_window_collection.push_back(_p_current_protein_detail_window);

  qDebug();
}

void
ProjectWindow::connectNewEngineDetailWindow()
{
  qDebug() << "";
  m_current_engine_detail_window = new EngineDetailWindow(this);
  m_engine_detail_window_collection.push_back(m_current_engine_detail_window);
}

void
ProjectWindow::connectNewMsRunListWindow()
{
  qDebug();
  _p_current_ms_identification_list_window =
    new MsIdentificationListWindow(this);

  _ms_identification_list_window_collection.push_back(
    _p_current_ms_identification_list_window);

  qDebug();
}

void
ProjectWindow::connectNewPeptideDetailWindow()
{
  qDebug() << " begin";
  _p_current_peptide_detail_window = new PeptideWindow(this);
  _peptide_detail_window_collection.push_back(_p_current_peptide_detail_window);

  qDebug() << " end";
}
void
ProjectWindow::connectNewPeptideListWindow()
{
  qDebug() << " begin";
  _p_current_peptide_list_window = new PeptideListWindow(this);
  _peptide_list_window_collection.push_back(_p_current_peptide_list_window);

  qDebug() << " end";
}
void
ProjectWindow::refreshPtmGroup(IdentificationGroup *p_ident_group)
{
  qDebug() << " begin";
  hideWaitingMessage();
  if(p_ident_group == nullptr)
    {
      qDebug() << " p_ident_group == nullptr";
    }
  else
    {
      try
        {
          emit identificationPtmGroupGrouped(p_ident_group);
        }
      catch(pappso::PappsoException &exception_pappso)
        {
          QMessageBox::warning(
            this, tr("Unable to display project :"), exception_pappso.qwhat());
        }
      catch(std::exception &exception_std)
        {
          QMessageBox::warning(
            this, tr("Unable to display project :"), exception_std.what());
        }
    }
  qDebug() << " end";
}
void
ProjectWindow::refreshGroup(IdentificationGroup *p_ident_group)
{
  qDebug() << " begin";
  hideWaitingMessage();
  if(p_ident_group == nullptr)
    {
      qDebug() << " p_ident_group == nullptr";
    }
  else
    {
      try
        {
          emit identificationGroupGrouped(p_ident_group);
        }
      catch(pappso::PappsoException &exception_pappso)
        {
          QMessageBox::warning(
            this, tr("Unable to display project :"), exception_pappso.qwhat());
        }
      catch(std::exception &exception_std)
        {
          QMessageBox::warning(
            this, tr("Unable to display project :"), exception_std.what());
        }
    }
  qDebug() << " end";
}

void
ProjectWindow::computeFdr()
{
  qDebug() << " begin ";
  try
    {
      ValidationState state     = ValidationState::valid;
      std::size_t total_prot    = 0;
      std::size_t false_prot    = 0;
      std::size_t total_peptide = 0;
      std::size_t false_peptide = 0;
      std::size_t total_psm     = 0;
      std::size_t false_psm     = 0;
      for(IdentificationGroup *identification_group :
          msp_project.get()->getIdentificationGroupList())
        {
          qDebug() << identification_group;
          total_prot += identification_group->countProteinMatch(state);
          qDebug() << "total_prot=" << total_prot;
          false_prot += identification_group->countDecoyProteinMatch(state);
          qDebug();
          total_psm += identification_group->countPeptideEvidence(state);
          qDebug() << "count pe";
          false_psm += identification_group->countDecoyPeptideEvidence(state);
          qDebug();

          total_peptide += identification_group->countPeptideMassSample(state);
          qDebug();
          false_peptide +=
            identification_group->countDecoyPeptideMassSample(state);
        }
      qDebug();
      ui->protein_fdr_label->setText(QString("%1 %").arg(QString::number(
        (Utils::computeFdr(false_prot, total_prot - false_prot)) * 100.0,
        'f',
        4)));
      ui->peptide_fdr_label->setText(QString("%1 %").arg(QString::number(
        (Utils::computeFdr(false_peptide, total_peptide - false_peptide)) *
          100.0,
        'f',
        4)));
      ui->psm_fdr_label->setText(QString("%1 %").arg(QString::number(
        (Utils::computeFdr(false_psm, total_psm - false_psm)) * 100.0,
        'f',
        4)));
      qDebug();
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      QMessageBox::warning(
        this, tr("Unable to compute FDR :"), exception_pappso.qwhat());
    }
  catch(std::exception &exception_std)
    {
      QMessageBox::warning(
        this, tr("Unable to compute FDR :"), exception_std.what());
    }
  qDebug() << " end";
}

void
ProjectWindow::computeMassPrecision()
{
  qDebug() << " begin";
  try
    {
      ValidationState state = ValidationState::validAndChecked;
      std::vector<pappso::pappso_double> delta_list;
      pappso::Enums::PrecisionUnit unit = pappso::Enums::PrecisionUnit::dalton;
      if(ui->precision_unit_combobox->currentText() == "ppm")
        {
          unit = pappso::Enums::PrecisionUnit::ppm;
        }

      for(IdentificationGroup *identification_group :
          msp_project.get()->getIdentificationGroupList())
        {
          identification_group->collectMhDelta(delta_list, unit, state);
        }

      std::sort(delta_list.begin(), delta_list.end());

      qDebug() << " accumulate";
      pappso::pappso_double sum =
        std::accumulate(delta_list.begin(), delta_list.end(), 0);

      qDebug() << " delta_list.size()=" << delta_list.size();
      pappso::pappso_double mean = 0;
      if(delta_list.size() > 0)
        {
          mean = sum / ((pappso::pappso_double)delta_list.size());
        }
      else
        {
          throw pappso::PappsoException(QObject::tr(
            "division by zero : no valid peptide found. Please check your "
            "filter parameters (decoy regexp or database particularly)"));
        }

      pappso::pappso_double median = delta_list[(delta_list.size() / 2)];


      qDebug() << " sd";
      pappso::pappso_double sd = 0;
      for(pappso::pappso_double val : delta_list)
        {
          // sd = sd + ((val - mean) * (val - mean));
          sd += std::pow((val - mean), 2);
        }
      sd = sd / delta_list.size();
      sd = std::sqrt(sd);

      ui->mass_precision_mean_label->setText(QString::number(mean, 'f', 10));
      ui->mass_precision_median_label->setText(
        QString::number(median, 'f', 10));
      ui->mass_precision_sd_label->setText(QString::number(sd, 'f', 10));


      std::vector<std::pair<pappso::pappso_double, size_t>> histogram =
        Utils::getHistogram(delta_list, 100);
      // generate some data:
      QVector<double> x, y;
      for(std::pair<pappso::pappso_double, size_t> &mass_pair : histogram)
        {
          x.push_back(mass_pair.first);
          y.push_back(mass_pair.second);
        }

      QCPGraph *p_graph = ui->mass_histogram_widget->graph();
      p_graph->setData(x, y);
      p_graph->rescaleAxes(true);
      ui->mass_histogram_widget->rescaleAxes();
      ui->mass_histogram_widget->replot();
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      ui->mass_precision_mean_label->setText("0");
      ui->mass_precision_median_label->setText("0");
      ui->mass_precision_sd_label->setText("0");
      QMessageBox::warning(this,
                           tr("Unable to compute mass precision :"),
                           exception_pappso.qwhat());
    }
  catch(std::exception &exception_std)
    {
      ui->mass_precision_mean_label->setText("0");
      ui->mass_precision_median_label->setText("0");
      ui->mass_precision_sd_label->setText("0");
      QMessageBox::warning(
        this, tr("Unable to compute mass precision :"), exception_std.what());
    }
  qDebug() << "end";
}
void
ProjectWindow::refresh()
{
  qDebug() << "begin ";
  computeFdr();
  computeMassPrecision();
  qDebug() << "end ";
}

void
ProjectWindow::doContaminantSelectionChanged()
{
  qDebug();
  ui->apply_filter_button->setEnabled(true);
  qDebug();
}

void
ProjectWindow::doDecoySelectionChanged()
{
  qDebug();
  // ui->apply_fdr_button->setEnabled(true);
  qDebug();
}

void
ProjectWindow::doAutomaticFilterParametersChanged()
{
  qDebug() << " begin ";
  ui->apply_filter_button->setEnabled(true);
  qDebug() << " end ";
}

void
ProjectWindow::doOperationFailed(QString error)
{
  hideWaitingMessage();
  viewError(error);
}
void
ProjectWindow::doOperationFinished()
{
  hideWaitingMessage();
}

void
ProjectWindow::doDisplayLoadingMessage(QString message)
{
  qDebug() << " " << message;
  _p_waiting_message_dialog->message(message);
}

void
ProjectWindow::doDisplayLoadingMessagePercent(QString message, int value)
{
  qDebug() << message << " " << value;
  _p_waiting_message_dialog->message(message, value);
}

void
ProjectWindow::doDisplayLoadingPercent(int value)
{
  qDebug() << value;
  _p_waiting_message_dialog->percent(value);
}

void
ProjectWindow::doDisplaySubTaskPercent(int value)
{
  qDebug() << value;
  _p_waiting_message_dialog->subTaskPercent(value);
}


void
ProjectWindow::doGroupingFinished()
{
  qDebug() << " begin ";
  hideWaitingMessage();

  // re group
  for(IdentificationGroup *p_ident_group :
      msp_project.get()->getIdentificationGroupList())
    {
      refreshGroup(p_ident_group);
    }

  refresh();

  qDebug() << " end";
}


void
ProjectWindow::doMassPrecisionUnitChanged(QString combo_value)
{
  qDebug() << " begin " << combo_value;

  refresh();
  qDebug() << " end ";
}
void
ProjectWindow::doViewPeptideList(IdentificationGroup *p_ident_group,
                                 ProteinMatch *protein_match)
{


  qDebug() << " begin";
  if(_peptide_list_window_collection.size() == 0)
    {
      connectNewPeptideListWindow();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      connectNewPeptideListWindow();
    }


  _p_current_peptide_list_window->setProteinMatch(p_ident_group, protein_match);
  _p_current_peptide_list_window->show();
  //_p_current_peptide_list_window->raise();
  //_p_current_peptide_list_window->activateWindow();
  qDebug() << " end";
}


void
ProjectWindow::doViewPeptideEvidenceSpDetail(
  std::shared_ptr<PeptideEvidence> peptide_evidence_sp)
{
  m_memoryGuardPeptideEvidenceList.push_back(peptide_evidence_sp);
  doViewPeptideDetail(peptide_evidence_sp.get());
}


void
ProjectWindow::doViewPeptideDetail(PeptideEvidence *peptide_evidence)
{

  qDebug() << " begin " << peptide_evidence;
  if(_peptide_detail_window_collection.size() == 0)
    {
      connectNewPeptideDetailWindow();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      connectNewPeptideDetailWindow();
    }


  _p_current_peptide_detail_window->setPeptideEvidence(peptide_evidence);
  _p_current_peptide_detail_window->show();
  //_p_current_peptide_detail_window->raise();
  //_p_current_peptide_detail_window->activateWindow();

  emit peptideEvidenceSelected(peptide_evidence);
  qDebug() << " end";
}

void
ProjectWindow::doViewProteinDetail(ProteinMatch *protein_match)
{


  qDebug() << " begin";
  if(_protein_detail_window_collection.size() == 0)
    {
      connectNewProteinDetailWindow();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      connectNewProteinDetailWindow();
    }


  _p_current_protein_detail_window->setProteinMatch(protein_match);
  _p_current_protein_detail_window->show();
  //_p_current_protein_detail_window->raise();
  //_p_current_protein_detail_window->activateWindow();
  qDebug() << " end";
}

void
ProjectWindow::doViewEngineDetail(
  IdentificationDataSourceSp *identificationEngine)
{
  qDebug() << "begin";
  if(m_engine_detail_window_collection.size() == 0)
    {
      connectNewEngineDetailWindow();
      m_current_engine_detail_window->setIdentificationEngineParam(
        identificationEngine);
      m_current_engine_detail_window->show();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      connectNewEngineDetailWindow();
      m_current_engine_detail_window->setIdentificationEngineParam(
        identificationEngine);
      m_current_engine_detail_window->show();
    }

  qDebug() << "end";
}

void
ProjectWindow::popEngineDetailView()
{
  m_engine_detail_window_collection.pop_back();
}

void
ProjectWindow::doPtmIslandGrouping(IdentificationGroup *p_identification_group)
{

  if(p_identification_group->getPtmGroupingExperiment() == nullptr)
    {
      showWaitingMessage(tr("Computing PTM islands"));
      emit operatePtmGroupingOnIdentification(p_identification_group,
                                              getPtmMode());
    }
}

void
ProjectWindow::doViewPtmIslandList(IdentificationGroup *p_identification_group)
{
  qDebug() << " begin " << p_identification_group;
  // if (p_identification_group == nullptr) {
  //}
  if(_ptm_island_list_window_collection.size() == 0)
    {
      connectNewPtmIslandListWindow();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      connectNewPtmIslandListWindow();
    }


  _p_current_ptm_island_list_window->show();
  //_p_current_protein_list_window->raise();
  //_p_current_protein_list_window->activateWindow();

  qDebug() << " end " << p_identification_group;
  _p_current_ptm_island_list_window->setIdentificationGroup(
    p_identification_group);

  for(auto &id_group : msp_project.get()->getIdentificationGroupList())
    {
      doPtmIslandGrouping(id_group);
    }
  // emit identificationGroupGrouped(p_identification_group);
  qDebug() << " end";
}

void
ProjectWindow::doViewProteinList(IdentificationGroup *p_identification_group)
{
  qDebug() << "p_identification_group=" << p_identification_group;
  // if (p_identification_group == nullptr) {
  //}
  if(_protein_list_window_collection.size() == 0)
    {
      qDebug();
      connectNewProteinListWindow();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      qDebug();
      connectNewProteinListWindow();
    }


  _p_current_protein_list_window->show();
  _p_current_protein_list_window->raise();
  _p_current_protein_list_window->activateWindow();

  qDebug() << "p_identification_group=" << p_identification_group;
  _p_current_protein_list_window->setIdentificationGroup(
    p_identification_group);

  emit identificationGroupGrouped(p_identification_group);
  qDebug() << "p_identification_group=";
}

void
ProjectWindow::doViewMsIdentificationList()
{
  qDebug() << "ProjectWindow::doViewMsIdentificationList begin ";

  if(_ms_identification_list_window_collection.size() == 0)
    {
      connectNewMsRunListWindow();
    }
  Qt::KeyboardModifiers modifier = QApplication::keyboardModifiers();
  if(modifier == Qt::ControlModifier)
    {
      connectNewMsRunListWindow();
    }
  _p_current_ms_identification_list_window->show();
  _p_current_ms_identification_list_window->raise();
  _p_current_ms_identification_list_window->activateWindow();

  qDebug();

  auto identification_list = msp_project.get()
                               ->getIdentificationDataSourceStore()
                               .getIdentificationDataSourceList();
  _p_current_ms_identification_list_window->setIdentificationDataSourceSpList(
    identification_list);

  qDebug();
}

void
ProjectWindow::setProjectSp(ProjectSp project_sp)
{
  qDebug();

  if(project_sp.get() == msp_project.get())
    return;

  msp_project = project_sp;
  ui->contaminant_widget->getProjectContaminants(msp_project.get());
  ui->decoy_widget->getProjectDecoys(msp_project.get());


  qDebug() << " project getFastaFileList size="
           << msp_project.get()->getFastaFileStore().getFastaFileList().size();
  _fastafile_list = msp_project.get()->getFastaFileStore().getFastaFileList();

  for(auto &&p_window : _ptm_island_list_window_collection)
    {
      delete p_window;
    }
  _ptm_island_list_window_collection.clear();
  _p_current_ptm_island_list_window = nullptr;


  for(auto &&p_window : _peptide_list_window_collection)
    {
      delete p_window;
    }
  _peptide_list_window_collection.clear();
  _p_current_peptide_list_window = nullptr;

  for(auto &&p_window : _protein_list_window_collection)
    {
      delete p_window;
    }
  _protein_list_window_collection.clear();
  _p_current_protein_list_window = nullptr;

  for(auto &&p_window : _protein_detail_window_collection)
    {
      delete p_window;
    }
  _protein_detail_window_collection.clear();
  _p_current_protein_detail_window = nullptr;

  for(auto &&p_window : _peptide_detail_window_collection)
    {
      delete p_window;
    }
  _peptide_detail_window_collection.clear();
  _p_current_peptide_detail_window = nullptr;

  if(_p_identification_widget != nullptr)
    {
      delete _p_identification_widget;
    }

  std::vector<IdentificationGroup *> identification_list =
    msp_project.get()->getIdentificationGroupList();


  // doViewProteinList(identification_list[0]);

  // qDeleteAll(ui->identifications_widget->children());
  QLayoutItem *wItem;
  while((wItem = ui->identifications_widget->layout()->takeAt(0)))
    {
      wItem->widget()->setVisible(false);
      delete wItem;
    }

  if(_p_xic_window != nullptr)
    {
      _p_xic_window->clear();
      _p_xic_window->hide();
      delete _p_xic_window;
      _p_xic_window = nullptr;
    }

  qDebug() << "  size=" << identification_list.size();
  if(identification_list.size() == 1)
    {
      ui->identifications_combobox->setVisible(false);

      IdentificationGroupWidget *p_identification_widget =
        new IdentificationGroupWidget(this);
      p_identification_widget->setIdentificationGroup(this,
                                                      identification_list[0]);

      ui->identifications_widget->layout()->addWidget(p_identification_widget);

      refreshGroup(identification_list[0]);
    }
  else
    {
      ui->identifications_combobox->clear();
      ui->identifications_combobox->setVisible(true);

      for(IdentificationGroup *identification_group : identification_list)
        {
          IdentificationGroupWidget *p_identification_widget =
            new IdentificationGroupWidget(this);
          p_identification_widget->setVisible(false);


          ui->identifications_combobox->addItem(
            identification_group->getTabName(),
            QVariant::fromValue(p_identification_widget));

          p_identification_widget->setIdentificationGroup(this,
                                                          identification_group);

          ui->identifications_widget->layout()->addWidget(
            p_identification_widget);

          refreshGroup(identification_group);
        }
      ui->identifications_combobox->setCurrentIndex(0);
      qobject_cast<IdentificationGroupWidget *>(
        qvariant_cast<QObject *>(ui->identifications_combobox->itemData(
          ui->identifications_combobox->currentIndex())))
        ->setVisible(true);
    }

  AutomaticFilterParameters params =
    msp_project.get()->getAutomaticFilterParameters();

  ui->filter_parameter_widget->setAutomaticFilterParameters(params);
  //_protein_list_window->setIdentificationGroup(_project_sp.get()->getCurrentIdentificationGroupP());
  //_protein_list_window->show();

  refresh();
  this->setEnabled(true);

  qDebug();
  // check DeepProt engine to enable/disable dedicated GUI
  bool hasDeepProt = false;
  for(auto &identification_date_source : msp_project.get()
                                           ->getIdentificationDataSourceStore()
                                           .getIdentificationDataSourceList())
    {
      if(identification_date_source.get()->getIdentificationEngine() ==
         IdentificationEngine::SpecOMS)
        {
          hasDeepProt = true;
          break;
        }
    }

  qDebug();
  if(hasDeepProt)
    {
      qDebug();
      if(mpa_deepProtGui != nullptr)
        {
          delete mpa_deepProtGui;
          mpa_deepProtGui = nullptr;
        }
      if(mpa_deepProtGui == nullptr)
        {
          mpa_deepProtGui = new DeepProtGui(this, msp_project);
          qDebug();
        }
    }
  else
    {

      if(mpa_deepProtGui != nullptr)
        {
          delete mpa_deepProtGui;
          mpa_deepProtGui = nullptr;
        }
    }

  ui->project_name_line_edit->setText(msp_project.get()->getProjectName());
  qDebug();
  // doAutomaticFilterParametersChanged(params);
  // doFdrChanged();
}
void
ProjectWindow::doIdentificationsComboboxChanged(int index_in)
{

  qDebug();
  if(ui->identifications_combobox->isVisible())
    {
      for(int index = 0; index < ui->identifications_combobox->count(); index++)
        {
          qobject_cast<IdentificationGroupWidget *>(
            qvariant_cast<QObject *>(
              ui->identifications_combobox->itemData(index)))
            ->setVisible(false);
        }
      qobject_cast<IdentificationGroupWidget *>(
        qvariant_cast<QObject *>(
          ui->identifications_combobox->itemData(index_in)))
        ->setVisible(true);
    }
  qDebug();
}

void
ProjectWindow::editModifications()
{
  _p_edit_modifications->setProjectSp(msp_project);
  _p_edit_modifications->show();
  _p_edit_modifications->raise();
  _p_edit_modifications->activateWindow();
}

void
ProjectWindow::editLabelingMethods()
{
  _p_edit_label_methods->setProjectSp(msp_project);
  _p_edit_label_methods->show();
  _p_edit_label_methods->raise();
  _p_edit_label_methods->activateWindow();
}

void
ProjectWindow::deepProtPostProcessInterface()
{
  if(mpa_deepProtGui != nullptr)
    {
      mpa_deepProtGui->show();
      mpa_deepProtGui->raise();
      mpa_deepProtGui->activateWindow();
    }
}

void
ProjectWindow::hideWaitingMessage()
{

  _p_waiting_message_dialog->hide();
}

void
ProjectWindow::showWaitingMessage(const QString title)
{
  _p_waiting_message_dialog->setWindowTitle(title);
  _p_waiting_message_dialog->show();
  _p_waiting_message_dialog->raise();
  _p_waiting_message_dialog->activateWindow();
}

void
ProjectWindow::doIdentificationGroupEdited(
  IdentificationGroup *p_identification_group)
{
  showWaitingMessage(tr("Updating identification group"));

  qDebug() << "begin";
  emit operateGroupingOnIdentification(
    p_identification_group,
    msp_project.get()->getContaminantRemovalMode(),
    msp_project.get()->getGroupingType());
}

void
ProjectWindow::viewError(const QString &error)
{
  qWarning() << "ProjectWindow::viewError" << error;
  // QMessageBox::warning(
  //  this, tr("Oops! an error occurred in i2MassChroQ. Don't panic :"), error);
}


void
ProjectWindow::doAcceptedLabelingMethod()
{

  qDebug() << "begin";
  showWaitingMessage(tr("Apply labeling method"));

  LabelingMethodSp labeling_method_sp =
    _p_edit_label_methods->getLabelingMethodSp();
  msp_project.get()->setLabelingMethodSp(labeling_method_sp);
  //_p_edit_label_methods->applyLabelingMethodInProject();

  doDisplayLoadingMessage(tr("labeling peptides"));

  qDebug();
  emit operateGrouping(msp_project);
}


void
ProjectWindow::openInXicViewer(const PeptideEvidence *p_peptide_evidence)
{

  qDebug();
  if(_p_xic_window == nullptr)
    {
      _p_xic_window = new XicWindow(this);
    }

  _p_xic_window->show();

  _p_xic_window->addXic(p_peptide_evidence);
  qDebug();
}


void
ProjectWindow::doFilterChanged()
{
  ui->apply_filter_button->setEnabled(true);
  // ui->apply_fdr_button->setEnabled(true);
}

void
ProjectWindow::doApplyDecoy()
{
  // ui->apply_fdr_button->setEnabled(false);
  // doAutomaticFilterParametersChanged(automatic_filter);
  try
    {
      showWaitingMessage(tr("Updating decoy sequences"));

      doDisplayLoadingMessage(tr("tagging decoy proteins"));

      ui->decoy_widget->setProjectDecoys(msp_project.get());
      // doDisplayLoadingMessage(tr("updating FDR"));
      //_project_sp.get()->updateAutomaticFilters(automatic_filter);
      doDisplayLoadingMessage(tr("updating filters"));
      msp_project.get()->updateAutomaticFilters(
        msp_project.get()->getAutomaticFilterParameters());


      qDebug();

      emit filterChangeFinished();
      emit operateGrouping(msp_project);
      emit projectStatusChanged();
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_pappso.qwhat());
    }
  catch(std::exception &exception_std)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_std.what());
    }
}


void
ProjectWindow::doComputePsmQvalues()
{
  try
    {
      showWaitingMessage(tr("Computing q-values on PSM"));


      qDebug();

      ComputeQvalues values(msp_project.get());
      qDebug();
      hideWaitingMessage();
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_pappso.qwhat());
    }
  catch(std::exception &exception_std)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_std.what());
    }
}

void
ProjectWindow::doComputeTidd()
{
  try
    {
      showWaitingMessage(tr("Computing TIDD svm probabilities"));

      TiddParameters params;

      params.m_ms2precision = ui->precision_widget->getPrecision();
      params.m_iteration    = ui->max_iteration_spinbox->value();
      params.m_trainSize    = ui->max_train_size_spinbox->value();

      emit operateTiddComputing(msp_project, params);
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_pappso.qwhat());
    }
  catch(std::exception &exception_std)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_std.what());
    }
}

void
ProjectWindow::doApplyFilter()
{
  ui->apply_filter_button->setEnabled(false);
  AutomaticFilterParameters automatic_filter =
    ui->filter_parameter_widget->getAutomaticFilterParameters();
  // doAutomaticFilterParametersChanged(automatic_filter);
  try
    {
      showWaitingMessage(tr("Updating filters"));

      doDisplayLoadingMessage(tr("tagging contaminant proteins"));

      ui->contaminant_widget->setProjectContaminants(msp_project.get());
      doDisplayLoadingMessage(tr("updating filters"));
      qDebug();
      msp_project.get()->updateAutomaticFilters(automatic_filter);

      qDebug();
      hideWaitingMessage();
      qDebug();
      emit filterChangeFinished();
      emit operateGrouping(msp_project);
      emit projectStatusChanged();
    }
  catch(pappso::PappsoException &exception_pappso)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_pappso.qwhat());
    }
  catch(std::exception &exception_std)
    {
      hideWaitingMessage();
      QMessageBox::warning(
        this, tr("Error filtering results :"), exception_std.what());
    }
}

void
ProjectWindow::doProjectNameChanged(QString name)
{
  emit projectNameChanged(name);
}

void
ProjectWindow::doProjectStatusChanged()
{
  msp_project.get()->setProjectChangedStatus(true);
}

void
ProjectWindow::doBestMsRunForAlignmentFinished(MsRunSp msrun_sp)
{
  mp_mainWindow->hideWaitingMessage();
  emit bestMsRunFound(msrun_sp);
}

PtmMode
ProjectWindow::getPtmMode()
{
  PtmMode ptm_mode = msp_project.get()->getPtmMode();

  if(ptm_mode == PtmMode::none)
    {
      return PtmMode::phospho;
    }

  return ptm_mode;
}

void
ProjectWindow::doCleanMsRunReaders()
{
  if(msp_project.get() != nullptr)
    {
      for(MsRunSp ms_run_sp : msp_project.get()->getMsRunStore().getMsRunList())
        {
          qDebug() << "free reader of " << ms_run_sp.get()->getFileName();
          ms_run_sp.get()->freeMsRunReaderSp();
        }
    }
}

void
ProjectWindow::doOpenMassChroQDialog()
{
  emit operateMassChroqExportDialog();
}

void
ProjectWindow::doExportXicAreaToCsv(QString filename,
                                    std::vector<XicBox *> xic_boxs)
{
  qDebug() << "Export Xic to csv";
  showWaitingMessage("Export All XIC area to CSV");
  emit operateWriteXicAreaInCsv(filename, getProjectSP(), xic_boxs);
}
void
ProjectWindow::doExportXicAreaToCsvFinished()
{
  hideWaitingMessage();
  qDebug() << "Export Finished";
}

void
ProjectWindow::enableDeepProtStudio(bool enabled)
{
  mp_mainWindow->enableDeepProtStudio(enabled);
}

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

void
ProjectWindow::receiveTiddResults(TiddResults message)
{
  ui->tidd_results_text_label->setText(
    tr("SVM probability threshold for %1 FDR is %2")
      .arg(QString::number(message.fdr * 100.0, 'f', 4))
      .arg(message.svmProbThreshold));

  AutomaticFilterParameters params =
    ui->filter_parameter_widget->getAutomaticFilterParameters();
  params.setSvmprobThreshold(message.svmProbThreshold);
  ui->filter_parameter_widget->setAutomaticFilterParameters(params);
}

const QString
ProjectWindow::getProjectName() const
{
  return ui->project_name_line_edit->text();
}
