
/*******************************************************************************
 * Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>.
 *
 * This file is part of XTPcpp.
 *
 *     XTPcpp 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.
 *
 *     XTPcpp 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 XTPcpp.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

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

ProjectWindow::ProjectWindow(MainWindow *parent)
  : QMainWindow(parent), ui(new Ui::ProjectView)
{
  main_window = 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(main_window,
          &MainWindow::projectNameChanged,
          this,
          &ProjectWindow::doProjectNameChanged);
  connect(this,
          &ProjectWindow::projectStatusChanged,
          this,
          &ProjectWindow::doProjectStatusChanged);
  connect(main_window->getWorkerThread(),
          &WorkerThread::bestMsrunForAlignmentGroupFinished,
          this,
          &ProjectWindow::doBestMsRunForAlignmentFinished);
  connect(this,
          &ProjectWindow::operateMassChroqExportDialog,
          main_window,
          &MainWindow::doActionMassChroQ);

  //
  // grouping
  /*
  connect(this,
          &ProjectWindow::operateGrouping,
          main_window->getWorkerThread(),
          &WorkerThread::doGrouping);
          */
  main_window->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();
}

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

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

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() << "ProjectWindow::connectNewPeptideDetailWindow begin";
  _p_current_peptide_detail_window = new PeptideWindow(this);
  _peptide_detail_window_collection.push_back(_p_current_peptide_detail_window);

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

  qDebug() << "ProjectWindow::connectNewPeptideListWindow end";
}
void
ProjectWindow::refreshPtmGroup(IdentificationGroup *p_ident_group)
{
  qDebug() << "ProjectWindow::refreshPtmGroup begin";
  hideWaitingMessage();
  if(p_ident_group == nullptr)
    {
      qDebug() << "ProjectWindow::refreshPtmGroup 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() << "ProjectWindow::refreshPtmGroup end";
}
void
ProjectWindow::refreshGroup(IdentificationGroup *p_ident_group)
{
  qDebug() << "ProjectWindow::refreshGroup begin";
  hideWaitingMessage();
  if(p_ident_group == nullptr)
    {
      qDebug() << "ProjectWindow::refreshGroup 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() << "ProjectWindow::refreshGroup end";
}

void
ProjectWindow::computeFdr()
{
  qDebug() << "ProjectWindow::computeFdr 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 :
          _project_sp.get()->getIdentificationGroupList())
        {
          total_prot += identification_group->countProteinMatch(state);
          false_prot += identification_group->countDecoyProteinMatch(state);
          total_psm += identification_group->countPeptideEvidence(state);
          false_psm += identification_group->countDecoyPeptideEvidence(state);

          total_peptide += identification_group->countPeptideMassSample(state);
          false_peptide +=
            identification_group->countDecoyPeptideMassSample(state);
        }
      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)));
    }
  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() << "ProjectWindow::computeFdr end";
}

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

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


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

      qDebug() << "ProjectWindow::computeMassPrecision 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)"));
        }

      std::sort(delta_list.begin(), delta_list.end());
      pappso::pappso_double median = delta_list[(delta_list.size() / 2)];


      qDebug() << "ProjectWindow::computeMassPrecision 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() << "ProjectWindow::computeMassPrecision end";
}
void
ProjectWindow::refresh()
{
  qDebug() << "ProjectWindow::refresh begin ";
  computeFdr();
  computeMassPrecision();
  qDebug() << "ProjectWindow::refresh end ";
}

void
ProjectWindow::doContaminantSelectionChanged()
{
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  ui->apply_filter_button->setEnabled(true);
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}

void
ProjectWindow::doDecoySelectionChanged()
{
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  ui->apply_fdr_button->setEnabled(true);
  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}

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

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

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

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

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

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

  refresh();

  qDebug() << "ProjectWindow::doGroupingFinished end";
}


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

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


  qDebug() << "ProjectWindow::doViewPeptideList 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() << "ProjectWindow::doViewPeptideList end";
}

void
ProjectWindow::doViewPeptideDetail(PeptideEvidence *peptide_evidence)
{

  qDebug() << "ProjectWindow::doViewPeptideDetail 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() << "ProjectWindow::doViewPeptideDetail end";
}

void
ProjectWindow::doViewProteinDetail(ProteinMatch *protein_match)
{


  qDebug() << "ProjectWindow::doViewProteinDetail 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() << "ProjectWindow::doViewProteinDetail 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() << "ProjectWindow::doViewPtmIslandList 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() << "ProjectWindow::doViewPtmIslandList end "
           << p_identification_group;
  _p_current_ptm_island_list_window->setIdentificationGroup(
    p_identification_group);

  doPtmIslandGrouping(p_identification_group);
  // emit identificationGroupGrouped(p_identification_group);
  qDebug() << "ProjectWindow::doViewPtmIslandList 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 = _project_sp.get()
                               ->getIdentificationDataSourceStore()
                               .getIdentificationDataSourceList();
  _p_current_ms_identification_list_window->setIdentificationDataSourceSpList(
    identification_list);

  qDebug();
}

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

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

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


  qDebug() << " project getFastaFileList size="
           << _project_sp.get()->getFastaFileStore().getFastaFileList().size();
  _fastafile_list = _project_sp.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 =
    _project_sp.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() << " ProjectWindow::setProjectSp 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 =
    _project_sp.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();
  // doAutomaticFilterParametersChanged(params);
  // doFdrChanged();
}
void
ProjectWindow::doIdentificationsComboboxChanged(int index_in)
{

  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  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() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}

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

void
ProjectWindow::editLabelingMethods()
{
  _p_edit_label_methods->setProjectSp(_project_sp);
  _p_edit_label_methods->show();
  _p_edit_label_methods->raise();
  _p_edit_label_methods->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,
    _project_sp.get()->getContaminantRemovalMode(),
    _project_sp.get()->getGroupingType());
}

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


void
ProjectWindow::doAcceptedLabelingMethod()
{

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

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

  doDisplayLoadingMessage(tr("labeling peptides"));

  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  emit operateGrouping(_project_sp);
}


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

  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
  if(_p_xic_window == nullptr)
    {
      _p_xic_window = new XicWindow(this);
    }

  _p_xic_window->show();

  _p_xic_window->addXic(p_peptide_evidence);

  qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
}


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(_project_sp.get());
      // doDisplayLoadingMessage(tr("updating FDR"));
      //_project_sp.get()->updateAutomaticFilters(automatic_filter);
      doDisplayLoadingMessage(tr("updating filters"));
      _project_sp.get()->updateAutomaticFilters(
        _project_sp.get()->getAutomaticFilterParameters());


      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
      emit operateGrouping(_project_sp);
      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() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;

      ComputeQvalues values(_project_sp);
      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
      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::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(_project_sp.get());
      doDisplayLoadingMessage(tr("updating filters"));
      qDebug();
      _project_sp.get()->updateAutomaticFilters(automatic_filter);

      qDebug();
      hideWaitingMessage();
      qDebug();
      emit operateGrouping(_project_sp);
      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()
{
  _project_sp.get()->setProjectChangedStatus();
}

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

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

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

  return ptm_mode;
}

void
ProjectWindow::doCleanMsRunReaders()
{
  if(_project_sp.get() != nullptr)
    {
      for(MsRunSp ms_run_sp : _project_sp.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");
  QString project_name = getProjectSP()->getProjectName();
  emit operateWriteXicAreaInCsv(filename, project_name, xic_boxs);
}
void
ProjectWindow::doExportXicAreaToCsvFinished()
{
  hideWaitingMessage();
  qDebug() << "Export Finished";
}
