
/*******************************************************************************
 * 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/>.
 *
 * Contributors:
 *     Olivier Langella <olivier.langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include <QSettings>
#include <odsstream/odsdocwriter.h>
#include <odsstream/qtablewriter.h>
#include "peptidelistwindow.h"
#include "../../project_view/projectwindow.h"

#include "ui_peptide_view.h"

PeptideListQactionColumn::PeptideListQactionColumn(PeptideListWindow *parent,
                                                   PeptideListColumn column)
  : QAction(parent)
{

  this->setText(PeptideTableModel::getTitle(column));

  this->setCheckable(true);
  this->setChecked(parent->getPeptideListColumnDisplay(column));


  // evalue_action.setChecked(_display_evalue);
  // connect(p_action, SIGNAL(toggled(bool)), this,
  // SLOT(showEvalueColumn(bool)));
  _column                = column;
  _p_peptide_list_window = parent;

#if QT_VERSION >= 0x050000
  // Qt5 code
  connect(this,
          &PeptideListQactionColumn::toggled,
          this,
          &PeptideListQactionColumn::doToggled);
#else
  // Qt4 code
  connect(this, SIGNAL(toggled(bool)), this, SLOT(doToggled(bool)));
#endif
}

PeptideListQactionColumn::~PeptideListQactionColumn()
{
  // if (_p_ms_data_file != nullptr) delete _p_ms_data_file;
  qDebug();
}

void
PeptideListQactionColumn::doToggled(bool toggled)
{
  qDebug() << toggled;
  setChecked(toggled);
  _p_peptide_list_window->setPeptideListColumnDisplay(_column, toggled);

  qDebug();
}


PeptideListWindow::PeptideListWindow(ProjectWindow *parent)
  : QMainWindow(parent), ui(new Ui::PeptideView)
{
  _project_window = parent;
  ui->setupUi(this);

  _peptide_table_model_p = new PeptideTableModel(this);

  if(_project_window->getProjectP() != nullptr)
    {
      setWindowTitle(QString("%1 - Peptide list")
                       .arg(_project_window->getProjectP()->getProjectName()));
    }

  _p_proxy_model = new PeptideTableProxyModel(this, _peptide_table_model_p);
  _p_proxy_model->setSourceModel(_peptide_table_model_p);
  _p_proxy_model->setDynamicSortFilter(true);
  ui->tableView->setModel(_p_proxy_model);
  ui->tableView->setSortingEnabled(true);
  ui->tableView->horizontalHeader()->setSectionsMovable(true);
  ui->tableView->setAlternatingRowColors(true);

  // connect(ui->tableView, SIGNAL(clicked(const QModelIndex &)),
  // _p_proxy_model, SLOT(onTableClicked(const QModelIndex &)));


  QSettings settings;
  bool hide = settings.value("peptideview/hidenotvalid", "true").toBool();
  ui->actionValid_peptides->setChecked(hide);
  _p_proxy_model->hideNotValid(hide);
  hide = settings.value("peptideview/hidenotchecked", "false").toBool();
  ui->actionChecked_peptides->setChecked(hide);
  _p_proxy_model->hideNotChecked(hide);
  hide = settings.value("peptideview/hidenotgrouped", "false").toBool();

  ui->actionGrouped_peptides->setChecked(hide);

  _p_proxy_model->hideNotGrouped(hide);

  ui->scan_number_edit->setVisible(false);
  ui->msrun_auto_completion->setVisible(false);
  ui->mod_auto_completion->setVisible(false);
  ui->peptide_search_edit->setVisible(true);

  // Add the col name to the hide/show menu
  PeptideListQactionColumn *p_action;
  for(int i = 0; i < _peptide_table_model_p->columnCount(); i++)
    {
      p_action = new PeptideListQactionColumn(
        this, PeptideTableModel::getPeptideListColumn(i));
      ui->menu_Columns->addAction(p_action);
    }

  // Create the copying path menu
  mp_copyPathMenu = new QMenu();

  connect(_project_window,
          &ProjectWindow::identificationGroupGrouped,
          this,
          &PeptideListWindow::doIdentificationGroupGrouped);

  connect(this,
          &PeptideListWindow::peptideDataChanged,
          _peptide_table_model_p,
          &PeptideTableModel::onPeptideDataChanged);

  connect(ui->tableView,
          &QTableView::clicked,
          _p_proxy_model,
          &PeptideTableProxyModel::onTableClicked);
  connect(_peptide_table_model_p,
          &PeptideTableModel::layoutChanged,
          this,
          &PeptideListWindow::updateStatusBar);
  connect(ui->centralwidget,
          &QWidget::customContextMenuRequested,
          this,
          &PeptideListWindow::showContextMenu);
  connect(
    mp_copyPathMenu, &QMenu::triggered, this, &PeptideListWindow::doCopyPath);
  connect(_project_window,
          &ProjectWindow::projectNameChanged,
          this,
          &PeptideListWindow::doProjectNameChanged);

  doSearchOn(ui->search_combobox->currentText());
}

PeptideListWindow::~PeptideListWindow()
{
  // if (_p_ms_data_file != nullptr) delete _p_ms_data_file;
  delete ui;
  if(mp_copyPathMenu != nullptr)
    {
      delete mp_copyPathMenu;
    }
}

void
PeptideListWindow::closeEvent(QCloseEvent *event)
{
  if(mp_copyPathMenu != nullptr)
    {
      mp_copyPathMenu->hide();
    }
  event->accept();
}

void
PeptideListWindow::doIdentificationGroupGrouped(
  IdentificationGroup *p_identification_group [[maybe_unused]])
{
}
ProjectWindow *
PeptideListWindow::getProjectWindow()
{
  return _project_window;
}
void
PeptideListWindow::setProteinMatch(IdentificationGroup *p_identification_group,
                                   ProteinMatch *p_protein_match)
{
  if(_p_protein_match != p_protein_match)
    {
      _p_identification_group = p_identification_group;
      _p_protein_match        = p_protein_match;
      _peptide_table_model_p->setProteinMatch(p_protein_match);
      //_p_proxy_model->setSourceModel(_peptide_table_model_p);
      ui->description_label->setText(
        p_protein_match->getProteinXtpSp().get()->getDescription());
      ui->accession_label->setText(
        p_protein_match->getProteinXtpSp().get()->getAccession());
      updateStatusBar();


      QStringList msrun_list;
      for(MsRunSp msrun_sp : _p_identification_group->getMsRunSpList())
        {
          msrun_list << msrun_sp.get()->getFileName();
          qDebug() << msrun_sp.get()->getFileName();
        }
      QCompleter *completer = new QCompleter(msrun_list, this);
      completer->setCaseSensitivity(Qt::CaseInsensitive);

      completer->setCompletionMode(QCompleter::PopupCompletion);
      completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
      completer->setFilterMode(Qt::MatchContains);
      ui->msrun_auto_completion->setCompleter(completer);

      QStringList mod_list;
      for(pappso::AaModificationP mod : _project_window->getProjectP()
                                          ->getPeptideStore()
                                          .getModificationCollection())
        {
          mod_list << QString("[%1] %2 %3")
                        .arg(mod->getAccession())
                        .arg(mod->getName())
                        .arg(mod->getMass());
          // qDebug() << "ProteinListWindow::setIdentificationGroup " <<
          // msrun_sp.get()->getFilename();
        }
      completer = new QCompleter(mod_list, this);
      completer->setCaseSensitivity(Qt::CaseInsensitive);

      completer->setCompletionMode(QCompleter::PopupCompletion);
      completer->setModelSorting(QCompleter::CaseSensitivelySortedModel);
      completer->setFilterMode(Qt::MatchContains);
      ui->mod_auto_completion->setCompleter(completer);


      _p_proxy_model->sort((std::int8_t)PeptideListColumn::peptide_grouping_id,
                           Qt::AscendingOrder);


      _p_proxy_model->resteItemDelegates();
    }
}


void
PeptideListWindow::edited()
{
  qDebug();
  // emit dataChanged(index, index);

  _p_protein_match->updateAutomaticFilters(
    _project_window->getProjectP()->getAutomaticFilterParameters());
  _project_window->doIdentificationGroupEdited(_p_identification_group);
  // updateStatusBar();

  qDebug();
}
void
PeptideListWindow::doNotValidHide(bool hide)
{
  qDebug();
  _p_proxy_model->hideNotValid(hide);
  QSettings settings;
  settings.setValue("peptidelistview/hidenotvalid", QString("%1").arg(hide));
  emit peptideDataChanged();
  qDebug();
}

void
PeptideListWindow::doNotCheckedHide(bool hide)
{
  qDebug();
  _p_proxy_model->hideNotChecked(hide);
  QSettings settings;
  settings.setValue("peptidelistview/hidenotchecked", QString("%1").arg(hide));
  emit peptideDataChanged();
  qDebug();
}
void
PeptideListWindow::doNotGroupedHide(bool hide)
{
  qDebug();
  _p_proxy_model->hideNotGrouped(hide);
  QSettings settings;
  settings.setValue("peptidelistview/hidenotgrouped", QString("%1").arg(hide));
  emit peptideDataChanged();
  qDebug();
}


void
PeptideListWindow::askPeptideDetailView(PeptideEvidence *p_peptide_evidence)
{
  qDebug();
  _project_window->doViewPeptideDetail(p_peptide_evidence);
  qDebug();
  // updateStatusBar();
}

void
PeptideListWindow::doPeptideSearchEdit(QString protein_search_string)
{
  qDebug() << protein_search_string;
  _p_proxy_model->setPeptideSearchString(protein_search_string);
  emit peptideDataChanged();
}

void
PeptideListWindow::doModificationSearch(QString mod_search [[maybe_unused]])
{
  //_p_proxy_model->setMsrunFileSearch(msr_run_file_search);
  emit peptideDataChanged();
}
void
PeptideListWindow::doMsrunFileSearch(QString msr_run_file_search)
{
  qDebug() << msr_run_file_search;
  emit peptideDataChanged();
}
void
PeptideListWindow::doScanNumberSearch(int scan_num)
{
  qDebug() << scan_num;
  emit peptideDataChanged();
}
void
PeptideListWindow::doSearchOn(QString search_on)
{
  qDebug() << search_on;
  _p_proxy_model->setSearchOn(search_on);

  ui->scan_number_edit->setVisible(false);
  ui->msrun_auto_completion->setVisible(false);
  ui->peptide_search_edit->setVisible(false);
  ui->mod_auto_completion->setVisible(false);
  if(search_on == "MS run/scan")
    {

      qDebug() << search_on;
      ui->scan_number_edit->setVisible(true);
      ui->msrun_auto_completion->setVisible(true);
    }
  else if(search_on == "Modifications")
    {

      qDebug() << search_on;
      ui->mod_auto_completion->setVisible(true);
    }
  else
    {
      qDebug() << search_on;
      ui->peptide_search_edit->setVisible(true);
    }
  // emit proteinDataChanged();
  emit peptideDataChanged();
}

void
PeptideListWindow::updateStatusBar()
{
  if(_p_identification_group == nullptr)
    {
    }
  else
    {
      ui->statusbar->showMessage(
        tr("peptides all:%1 valid:%2 valid&checked:%3 displayed:%4")
          .arg(_p_protein_match->countPeptideMatch(ValidationState::notValid))
          .arg(_p_protein_match->countPeptideMatch(ValidationState::valid))
          .arg(_p_protein_match->countPeptideMatch(
            ValidationState::validAndChecked))
          .arg(_p_proxy_model->rowCount()));
    }
}

void
PeptideListWindow::resizeColumnsToContents()
{
  ui->tableView->resizeColumnsToContents();
}


void
PeptideListWindow::showContextMenu(const QPoint &pos)
{
  QModelIndex corrected_index =
    _p_proxy_model->mapToSource(ui->tableView->indexAt(pos));

  qDebug() << "check the column" << corrected_index.column();

  // Handle the file path copy to clipboard
  if(corrected_index.column() == (std::int8_t)PeptideListColumn::sample)
    {
      mp_copyPathMenu->clear();
      QAction *copy_action =
        new QAction(QIcon::fromTheme("edit-copy"), "copy path");
      mp_copyPathMenu->addAction(copy_action);
      m_askIndex = corrected_index;
      mp_copyPathMenu->exec(QCursor::pos());
    }
}

void
PeptideListWindow::doCopyPath(QAction *action)
{
  QString path;
  if(action->text() == "copy path")
    {

      if(m_askIndex.column() == (std::int8_t)PeptideListColumn::sample)
        {
          path = _peptide_table_model_p->getProteinMatch()
                   ->getPeptideMatchList()
                   .at(m_askIndex.row())
                   .getPeptideEvidence()
                   ->getIdentificationDataSource()
                   ->getMsRunSp()
                   ->getFileName();
        }
      qDebug() << path << "copied";
      QClipboard *clipboard = QGuiApplication::clipboard();
      clipboard->setText(path);
    }
}

void
PeptideListWindow::setPeptideListColumnDisplay(PeptideListColumn column,
                                               bool toggled)
{
  _p_proxy_model->setPeptideListColumnDisplay(column, toggled);
}
/*
void PeptideListWindow::resizeColumnsToContents() {
    ui->tableView->resizeColumnsToContents();
}
*/

bool
PeptideListWindow::getPeptideListColumnDisplay(PeptideListColumn column) const
{
  return _p_proxy_model->getPeptideListColumnDisplay(column);
}

void
PeptideListWindow::doExportAsOdsFile()
{
  qDebug();
  QSettings settings;
  QString default_location = settings.value("path/export_ods", "").toString();

  QString filename;
  filename = QFileDialog::getSaveFileName(
    this,
    tr("Save ODS file"),
    QString("%1/untitled.ods").arg(default_location),
    tr("Open Document Spreadsheet (*.ods)"));

  if(!filename.isEmpty())
    {


      CalcWriterInterface *p_writer = new OdsDocWriter(filename);
      p_writer->writeSheet("Protein");
      p_writer->writeCell("Accession");
      p_writer->writeCell(
        _p_protein_match->getProteinXtpSp().get()->getAccession());
      p_writer->writeLine();
      p_writer->writeCell("Description");
      p_writer->writeCell(
        _p_protein_match->getProteinXtpSp().get()->getDescription());
      p_writer->writeLine();
      p_writer->writeCell("Sequence");
      p_writer->writeCell(
        _p_protein_match->getProteinXtpSp().get()->getSequence());
      p_writer->writeLine();


      const QAbstractProxyModel *p_table_model = _p_proxy_model;

      QtableWriter table_writer(p_writer, p_table_model);

      // table_writer.setFormatPercentForColumn(
      //  _peptide_table_model_p->index(0, (int)ProteinListColumn::coverage));

      table_writer.writeSheet("peptide list");

      p_writer->close();
      delete p_writer;
    }
}

void
PeptideListWindow::doProjectNameChanged(QString name)
{
  setWindowTitle(tr("%1 - Peptide list").arg(name));
}
