
/*******************************************************************************
 * 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 <QDebug>
#include <QSettings>
#include <pappsomspp/core/pappsoexception.h>
#include "ui_peptide_view.h"
#include "peptidetableproxymodel.h"
#include "peptidelistwindow.h"
#include "../../project_view/projectwindow.h"

PeptideTableProxyModel::PeptideTableProxyModel(
  PeptideListWindow *p_peptide_list_window,
  PeptideTableModel *peptide_table_model_p)
  : QSortFilterProxyModel(peptide_table_model_p)
{
  _peptide_table_model_p = peptide_table_model_p;
  _p_peptide_list_window = p_peptide_list_window;
  _column_display.resize(peptide_table_model_p->columnCount());
  QSettings settings;

  for(std::size_t i = 0; i < _column_display.size(); i++)
    {
      _column_display[i] =
        settings.value(QString("peptide_list_columns/c%1").arg(i), "true")
          .toBool();
    }
  _mass_delegate   = new MassItemDelegate(_p_peptide_list_window);
  _minute_delegate = new MinuteItemDelegate(_p_peptide_list_window);
  _second_delegate = new SecondItemDelegate(_p_peptide_list_window);
}

PeptideTableProxyModel::~PeptideTableProxyModel()
{
  // delete _mass_delegate ;
  // delete _minute_delegate ;
  // delete _second_delegate ;
}

bool
PeptideTableProxyModel::filterAcceptsColumn(int source_column,
                                            const QModelIndex &source_parent
                                            [[maybe_unused]]) const
{
  PeptideListColumn peptide_column =
    _peptide_table_model_p->getPeptideListColumn(source_column);
  if(_column_display[(int)peptide_column])
    {

      if(peptide_column == PeptideListColumn::label)
        {
          if(_p_peptide_list_window->getProjectWindow()
               ->getProjectP()
               ->getLabelingMethodSp()
               .get() == nullptr)
            {
              return false;
            }
        }
      if(_peptide_table_model_p->hasColumn(peptide_column))
        {
          return _column_display[(int)peptide_column];
        }
    }
  return false;
}

bool
PeptideTableProxyModel::filterAcceptsRow(int source_row,
                                         const QModelIndex &source_parent
                                         [[maybe_unused]]) const
{
  try
    {
      qDebug() << " begin " << source_row;
      PeptideEvidence *peptide_evidence =
        _peptide_table_model_p->getProteinMatch()
          ->getPeptideMatchList()
          .at(source_row)
          .getPeptideEvidence();
      qDebug() << "protein_match " << source_row;

      qDebug() << " valid ";
      if(_hide_not_valid)
        {
          if(!peptide_evidence->isValid())
            {
              return false;
            }
        }
      qDebug() << " checked ";
      if(_hide_not_checked)
        {
          if(!peptide_evidence->isChecked())
            {
              return false;
            }
        }

      qDebug() << "grouped ";
      if(_hide_not_grouped)
        {
          if(!peptide_evidence->isGrouped())
            {
              return false;
            }
        }

      if(_search_on == "MS run/scan")
        {
          unsigned int scan_num =
            this->_p_peptide_list_window->ui->scan_number_edit->value();
          QString file_search_string =
            this->_p_peptide_list_window->ui->msrun_auto_completion->text()
              .toLower();
          qDebug() << " MS run/scan " << file_search_string << " " << scan_num;
          bool scan_ok = true;
          if(scan_num > 0)
            {
              scan_ok = false;
              if(peptide_evidence->getScanNumber() == scan_num)
                {
                  scan_ok = true;
                }
            }
          bool msrun_ok = true;
          if(!file_search_string.isEmpty())
            {
              msrun_ok = false;
              if(peptide_evidence->getMsRunP()
                   ->getFileName()
                   .toLower()
                   .contains(file_search_string))
                {
                  msrun_ok = true;
                }
            }
          if(msrun_ok && scan_ok)
            {
              return true;
            }

          return false;
        }

      if(!_peptide_search_string.isEmpty())
        {
          if(_search_on == "Pep. seq.")
            {
              if(!peptide_evidence->getPeptideXtpSp()
                    .get()
                    ->getSequence()
                    .contains(_peptide_search_string))
                {
                  return false;
                }
            }
          else if(_search_on == "Sample")
            {
              if(!peptide_evidence->getMsRunP()->getSampleName().contains(
                   _peptide_search_string))
                {
                  return false;
                }
            }
          else if(_search_on == "Subgroup")
            {
              if(peptide_evidence->getValidationState() !=
                 ValidationState::grouped)
                {
                  return false;
                }
              // unsigned int subgroup = _peptide_search_string.toUInt();
              return false;
            }
          else if(_search_on == "Modification")
            {
              return false;
            }
        }


      if(_search_on == "Modifications")
        {
          QString mod_search_string =
            this->_p_peptide_list_window->ui->mod_auto_completion->text();

          std::vector<pappso::AaModificationP> mod_list;
          for(pappso::AaModificationP mod :
              _p_peptide_list_window->getProjectWindow()
                ->getProjectP()
                ->getPeptideStore()
                .getModificationCollection())
            {
              if(QString("[%1] %2 %3")
                   .arg(mod->getAccession())
                   .arg(mod->getName())
                   .arg(mod->getMass())
                   .contains(mod_search_string))
                {
                  mod_list.push_back(mod);
                }
              // qDebug() << "ProteinListWindow::setIdentificationGroup " <<
              // msrun_sp.get()->getFilename();
            }
          // qDebug() << "ProteinTableProxyModel::filterAcceptsRow msrun/scan "
          // << file_search_string << " " << scan_num;
          for(pappso::AaModificationP mod : mod_list)
            {
              if(peptide_evidence->getPeptideXtpSp()
                   .get()
                   ->getNumberOfModification(mod) > 0)
                {
                  return true;
                }
            }
          return false;
        }
      return true;
    }

  catch(pappso::PappsoException &exception_pappso)
    {
      // QMessageBox::warning(this,
      //                     tr("Error in ProteinTableModel::acceptRow :"),
      //                     exception_pappso.qwhat());
      qDebug() << "Error in PeptideTableProxyModel::acceptRow :"
               << exception_pappso.qwhat();
    }
  catch(std::exception &exception_std)
    {
      // QMessageBox::warning(this,
      //                    tr("Error in ProteinTableModel::acceptRow :"),
      //                    exception_std.what());
      qDebug() << "Error in PeptideTableProxyModel::acceptRow :"
               << exception_std.what();
    }

  return true;

  // return true;
}


void
PeptideTableProxyModel::onTableClicked(const QModelIndex &index)
{
  qDebug() << "begin " << index.row();
  qDebug() << "begin " << this->mapToSource(index).row();

  //_protein_table_model_p->onTableClicked(this->mapToSource(index));
  QModelIndex source_index(this->mapToSource(index));
  int row               = source_index.row();
  PeptideListColumn col = (PeptideListColumn)source_index.column();
  PeptideMatch *peptide_match =
    &_peptide_table_model_p->getProteinMatch()->getPeptideMatchList().at(row);
  if(col == PeptideListColumn::checked) // add a checkbox to cell(1,0)
    {

      if(peptide_match->getPeptideEvidence()->isChecked())
        {
          peptide_match->getPeptideEvidence()->setChecked(false);
        }
      else
        {
          peptide_match->getPeptideEvidence()->setChecked(true);
        }
      _p_peptide_list_window->edited();
    }
  else
    {
      _p_peptide_list_window->askPeptideDetailView(
        peptide_match->getPeptideEvidence());
    }
  qDebug() << " end " << index.row();
}

bool
PeptideTableProxyModel::lessThan(const QModelIndex &left,
                                 const QModelIndex &right) const
{
  QVariant leftData  = sourceModel()->data(left);
  QVariant rightData = sourceModel()->data(right);
  if(leftData.typeId() == QMetaType::UInt)
    {
      return leftData.toUInt() < rightData.toUInt();
    }
  if(leftData.typeId() == QMetaType::UInt)
    {
      return leftData.toUInt() < rightData.toUInt();
    }
  if(leftData.typeId() == QMetaType::Double)
    {
      return leftData.toDouble() < rightData.toDouble();
    }
  return leftData.toString() < rightData.toString();
}


QVariant
PeptideTableProxyModel::headerData(int section,
                                   Qt::Orientation orientation,
                                   int role) const
{
  int col = mapToSource(index(0, section)).column();

  return sourceModel()->headerData(col, orientation, role);
}

QVariant
PeptideTableProxyModel::data(const QModelIndex &index, int role) const
{

  // auto new_index = this->index(index.row(), mapToSource(index).column());
  return sourceModel()->data(mapToSource(index), role);
}

void
PeptideTableProxyModel::hideNotValid(bool hide)
{
  _hide_not_valid = hide;
}

void
PeptideTableProxyModel::hideNotChecked(bool hide)
{
  qDebug() << "begin ";
  _hide_not_checked = hide;
  qDebug() << " end ";
}
void
PeptideTableProxyModel::hideNotGrouped(bool hide)
{
  _hide_not_grouped = hide;
}

void
PeptideTableProxyModel::setSearchOn(QString search_on)
{
  _search_on = search_on;
}
void
PeptideTableProxyModel::setPeptideSearchString(QString peptide_search_string)
{
  _peptide_search_string = peptide_search_string;
}

bool
PeptideTableProxyModel::getPeptideListColumnDisplay(
  PeptideListColumn column) const
{
  return _column_display[(std::int8_t)column];
}
void
PeptideTableProxyModel::setPeptideListColumnDisplay(PeptideListColumn column,
                                                    bool toggled)
{
  qDebug() << " begin " << toggled;
  beginResetModel();
  QSettings settings;
  settings.setValue(
    QString("peptide_list_columns/c%1").arg((std::int8_t)column), toggled);
  _column_display[(std::int8_t)column] = toggled;

  endResetModel();

  resteItemDelegates();

  // emit columnsRemoved(createIndex(1, 2), (int) column, (int) column)
}


void
PeptideTableProxyModel::resteItemDelegates() const
{

  for(int i = 0; i < columnCount(); ++i)
    {
      _p_peptide_list_window->ui->tableView->setItemDelegateForColumn(
        i, _p_peptide_list_window->ui->tableView->itemDelegate());
      if(mapToSource(index(0, i)).column() ==
         (std::int8_t)PeptideListColumn::experimental_mhplus)
        {
          _p_peptide_list_window->ui->tableView->setItemDelegateForColumn(
            i, _mass_delegate);
        }
      if(mapToSource(index(0, i)).column() ==
         (std::int8_t)PeptideListColumn::theoretical_mhplus)
        {
          _p_peptide_list_window->ui->tableView->setItemDelegateForColumn(
            i, _mass_delegate);
        }
      if(mapToSource(index(0, i)).column() ==
         (std::int8_t)PeptideListColumn::experimental_mz)
        {
          _p_peptide_list_window->ui->tableView->setItemDelegateForColumn(
            i, _mass_delegate);
        }
      if(mapToSource(index(0, i)).column() ==
         (std::int8_t)PeptideListColumn::rtmin)
        {
          _p_peptide_list_window->ui->tableView->setItemDelegateForColumn(
            i, _minute_delegate);
        }
      if(mapToSource(index(0, i)).column() ==
         (std::int8_t)PeptideListColumn::rt)
        {
          _p_peptide_list_window->ui->tableView->setItemDelegateForColumn(
            i, _second_delegate);
        }
    }
  /*
   MinuteItemDelegate * minute_delegate = new MinuteItemDelegate(ui->tableView);
   ui->tableView->setItemDelegateForColumn((std::int8_t)
   PeptideListColumn::rtmin, minute_delegate); SecondItemDelegate *
   second_delegate = new SecondItemDelegate(ui->tableView);
   ui->tableView->setItemDelegateForColumn((std::int8_t) PeptideListColumn::rt,
   second_delegate);
  */
}
