/**
 * \file src/gui/edit/deepprot_gui/deepprotgui.cpp
 * \date 27/1/2021
 * \author Olivier Langella
 * \brief GUI dedicated to DeepProt postprocessing
 */


/*******************************************************************************
 * Copyright (c) 2021 Olivier Langella
 *<Olivier.Langella@universite-paris-saclay.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 "deepprotgui.h"
#include "ui_deepprot_gui.h"
#include "../../project_view/projectwindow.h"


DeepProtGui::DeepProtGui(ProjectWindow *parent, ProjectSp project_sp)
  : QMainWindow(parent), ui(new Ui::DeepProtGui)
{
  qDebug();
  ui->setupUi(this);
  mp_projectWindow = parent;
  msp_project      = project_sp;
  mp_projectWindow->enableDeepProtStudio(true);
  ui->selectedPeptideEvidenceLabel->setText("");
  ui->currentPeptideEvidenceLabel->setText("");

  setWindowTitle(
    QString("%1 - DeepProt studio").arg(msp_project.get()->getProjectName()));

  // list of mass delta :

  setPeptideEvidenceList();


  connect(parent,
          &ProjectWindow::filterChangeFinished,
          this,
          &DeepProtGui::doFilterChangeFinished);
  connect(parent,
          &ProjectWindow::projectNameChanged,
          this,
          &DeepProtGui::doProjectNameChanged);
  connect(ui->massDeltaWidget,
          &MassDeltaWidget::peptideEvidenceChanged,
          this,
          &DeepProtGui::doPeptideEvidenceChanged);
  connect(ui->massDeltaWidget,
          &MassDeltaWidget::selectedPeptideEvidenceChanged,
          this,
          &DeepProtGui::doSelectedPeptideEvidenceChanged);

  qDebug();
}

void
DeepProtGui::closeEvent(QCloseEvent *event)
{
  qDebug();
  if(mpa_modificationBrowser != nullptr)
    {
      mpa_modificationBrowser->close();
    }
  QWidget::closeEvent(event);
}


void
DeepProtGui::doFilterChangeFinished()
{
  setPeptideEvidenceList();
  update();
}

void
DeepProtGui::doProjectNameChanged(QString name)
{
  setWindowTitle(tr("%1 - DeepProt studio").arg(name));
}

void
DeepProtGui::setPeptideEvidenceList()
{
  qDebug();
  ui->massDeltaWidget->clearPeptideEvidenceList();

  IdentificationDataSourceStore identification_data_source_store =
    msp_project.get()->getIdentificationDataSourceStore();
  ValidationState state = ValidationState::validAndChecked;
  std::vector<pappso::pappso_double> delta_list;

  std::vector<std::shared_ptr<PeptideEvidence>> valid_and_checked_pe_list;
  for(IdentificationDataSourceSp identification_data_source :
      identification_data_source_store.getIdentificationDataSourceList())
    {
      auto total_pe_list = identification_data_source.get()
                             ->getPeptideEvidenceStore()
                             .getPeptideEvidenceList();
      for(auto &pe : total_pe_list)
        {
          if(pe.get()->getValidationState() >= state)
            {
              valid_and_checked_pe_list.push_back(pe);
            }
        }
    }
  ui->massDeltaWidget->addPeptideEvidenceList(msp_project.get(),
                                              valid_and_checked_pe_list);

  qDebug();
}


DeepProtGui::~DeepProtGui()
{
  // mp_projectWindow->enableDeepProtStudio(false);
  qDebug();
  delete ui;

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

void
DeepProtGui::doPeptideEvidenceChanged(
  std::shared_ptr<PeptideEvidence> peptide_evidence_sp)
{
  qDebug();
  if(peptide_evidence_sp == nullptr)
    {
      ui->currentPeptideEvidenceLabel->setText("");
    }
  else
    {

      QString position_str;
      QVariant param = peptide_evidence_sp.get()->getParam(
        PeptideEvidenceParam::deepprot_delta_positions);
      if(!param.isNull())
        {
          position_str = param.toString();
        }


      ui->currentPeptideEvidenceLabel->setText(
        QString("%1 - %2 - %3")
          .arg(peptide_evidence_sp.get()->getHtmlSequence())
          .arg(peptide_evidence_sp.get()->getDeltaMass())
          .arg(position_str));
    }
}

void
DeepProtGui::doSelectedPeptideEvidenceChanged(
  std::shared_ptr<PeptideEvidence> peptide_evidence_sp)
{
  qDebug();
  msp_selectedPeptideEvidence = peptide_evidence_sp;
  if(peptide_evidence_sp == nullptr)
    {
      ui->selectedPeptideEvidenceLabel->setText("");
    }
  else
    {

      QString position_str;
      QVariant param = peptide_evidence_sp.get()->getParam(
        PeptideEvidenceParam::deepprot_delta_positions);
      if(!param.isNull())
        {
          position_str = param.toString();
        }


      ui->selectedPeptideEvidenceLabel->setText(
        QString("%1 - %2 - %3")
          .arg(peptide_evidence_sp.get()->getHtmlSequence())
          .arg(peptide_evidence_sp.get()->getDeltaMass())
          .arg(position_str));

      m_alternativePeptideEvidenceList.clear();
      m_alternativePeptideEvidenceList =
        generatePeptideEvidenceSolutions(peptide_evidence_sp);

      addPushButtonAlternativeSequences();

      if((mpa_modificationBrowser != nullptr) &&
         (msp_selectedPeptideEvidence.get() != nullptr))
        {
          mpa_modificationBrowser->setMzTarget(
            msp_selectedPeptideEvidence.get()->getDeltaMass());
        }
    }
}


void
DeepProtGui::doClickPeptideDetailView()
{

  if(msp_selectedPeptideEvidence.get() != nullptr)
    {
      mp_projectWindow->doViewPeptideEvidenceSpDetail(
        msp_selectedPeptideEvidence);
    }
}


std::vector<std::shared_ptr<PeptideEvidence>>
DeepProtGui::generatePeptideEvidenceSolutions(
  std::shared_ptr<PeptideEvidence> &peptide_evidence_sp) const
{
  std::vector<std::shared_ptr<PeptideEvidence>> solution_list;
  std::vector<std::size_t> position_list;
  QVariant param = peptide_evidence_sp.get()->getParam(
    PeptideEvidenceParam::deepprot_delta_positions);
  if(!param.isNull())
    {
      for(auto pos_str : param.toString().split(" ", Qt::SkipEmptyParts))
        {
          position_list.push_back(pos_str.toUInt());
        }
    }
  if(position_list.size() > 0)
    {
      std::sort(position_list.begin(),
                position_list.end(),
                [](std::size_t a, std::size_t b) { return a < b; });

      pappso::AaModificationP modification =
        pappso::AaModification::getInstanceCustomizedMod(
          peptide_evidence_sp.get()->getDeltaMass());
      qDebug();
      for(std::size_t pos : position_list)
        {
          qDebug();
          PeptideXtpSp peptide_sp =
            PeptideXtp(*(peptide_evidence_sp.get()->getPeptideXtpSp().get()))
              .makePeptideXtpSp();

          qDebug() << peptide_sp.get()->toAbsoluteString();
          peptide_sp.get()->addAaModification(modification, pos);

          qDebug() << peptide_sp.get()->toAbsoluteString();
          PeptideEvidenceSp pe = PeptideEvidence(*(peptide_evidence_sp.get()))
                                   .makePeptideEvidenceSp();
          pe.get()->setPeptideXtpSp(peptide_sp);

          qDebug();
          solution_list.push_back(pe);
          qDebug() << pe.get()->getHtmlSequence();
        }
    }
  qDebug();
  return solution_list;
}

void
DeepProtGui::addPushButtonAlternativeSequences()
{
  QLayoutItem *child;
  while((child = ui->qboxAlternativePeptideLayout->takeAt(0)) != 0)
    {
      if(child->widget() != NULL)
        {
          delete(child->widget());
        }
      delete child;
    }

  for(auto pe : m_alternativePeptideEvidenceList)
    {
      QPushButton *newButton = new QPushButton;
      newButton->setText(pe.get()->getPeptideXtpSp().get()->toString());
      newButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
      ProjectWindow *p_project = mp_projectWindow;
      connect(newButton, &QPushButton::clicked, [pe, p_project]() {
        qDebug() << "clicked" << pe.get()->getPeptideXtpSp().get()->toString();
        p_project->doViewPeptideEvidenceSpDetail(pe);
      });
      ui->qboxAlternativePeptideLayout->addWidget(newButton);
    }
}

void
DeepProtGui::showModificationsBrowser()
{
  if(mpa_modificationBrowser == nullptr)
    {
      qDebug() << mpa_modificationBrowser;
      mpa_modificationBrowser = new ModificationBrowser(this);
      mpa_modificationBrowser->setPrecision(
        pappso::PrecisionFactory::getDaltonInstance(0.02));
      qDebug();
    }
  qDebug() << mpa_modificationBrowser;
  if(msp_selectedPeptideEvidence.get() != nullptr)
    {
      mpa_modificationBrowser->setMzTarget(
        msp_selectedPeptideEvidence.get()->getDeltaMass());
    }

  qDebug();
  mpa_modificationBrowser->show();
}
