/**
 * \file gui/ptm_peptide_list_window/ptmpeptidetablemodel.cpp
 * \date 10/6/2017
 * \author Olivier Langella
 */

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

#include "ptmpeptidetablemodel.h"
#include "ptmpeptidelistwindow.h"
#include <QDebug>
#include <QStringList>

PtmPeptideTableModel::PtmPeptideTableModel(
  PtmPeptideListWindow *p_ptm_peptide_list_window [[maybe_unused]])
{
}

PtmPeptideTableModel::~PtmPeptideTableModel()
{
}


const PtmGroupingExperiment *
PtmPeptideTableModel::getPtmGroupingExperiment() const
{
  return _p_ptm_grouping_experiment;
}
const std::vector<PtmSampleScanSp> &
PtmPeptideTableModel::getPtmSampleScanSpList() const
{
  return _ptm_sample_scan_list;
}

const QString
PtmPeptideTableModel::getTitle(PtmPeptideListColumn column)
{
  qDebug() << "PtmPeptideTableModel::getTitle begin ";
  return PtmPeptideTableModel::getTitle((std::int8_t)column);
  // qDebug() << "ProteinTableModel::getTitle end ";
}
const QString
PtmPeptideTableModel::getDescription(PtmPeptideListColumn column)
{
  qDebug() << "PtmPeptideTableModel::columnCount begin ";
  return PtmPeptideTableModel::getDescription((std::int8_t)column);
  // qDebug() << "ProteinTableModel::columnCount end ";
}

const QString
PtmPeptideTableModel::getTitle(std::int8_t column)
{
  switch(column)
    {

      case(std::int8_t)PtmPeptideListColumn::peptide_ptm_grouping_id:
        return "peptide ID";
        break;
      case(std::int8_t)PtmPeptideListColumn::sample:
        return "sample";
        break;
      case(std::int8_t)PtmPeptideListColumn::scan:
        return "scan";
        break;
      case(std::int8_t)PtmPeptideListColumn::rt:
        return "RT";
        break;
      case(std::int8_t)PtmPeptideListColumn::charge:
        return "charge";
        break;
      case(std::int8_t)PtmPeptideListColumn::sequence:
        return "sequence";
        break;
      case(std::int8_t)PtmPeptideListColumn::modifs:
        return "modifs";
        break;
      case(std::int8_t)PtmPeptideListColumn::start:
        return "start";
        break;
      case(std::int8_t)PtmPeptideListColumn::length:
        return "length";
        break;
      case(std::int8_t)PtmPeptideListColumn::bestEvalue:
        return "top Evalue";
        break;
      case(std::int8_t)PtmPeptideListColumn::theoretical_mhplus:
        return "theoretical MH+";
        break;
      case(std::int8_t)PtmPeptideListColumn::delta_mhplus:
        return "delta MH+";
        break;
      case(std::int8_t)PtmPeptideListColumn::besthyperscore:
        return "top hyperscore";
      case(std::int8_t)PtmPeptideListColumn::bestposition:
        return "top PTM positions";
      case(std::int8_t)PtmPeptideListColumn::allobservedposition:
        return "observed PTM positions";
    }
  return "";
}

const QString
PtmPeptideTableModel::getDescription(std::int8_t column)
{
  switch(column)
    {

      case(std::int8_t)PtmPeptideListColumn::peptide_ptm_grouping_id:
        return "unique PTM peptide identifier within this PTM grouping "
               "experiment";
        break;
      case(std::int8_t)PtmPeptideListColumn::sample:
        return "MS sample name";
        break;
      case(std::int8_t)PtmPeptideListColumn::scan:
        return "scan number";
        break;
      case(std::int8_t)PtmPeptideListColumn::rt:
        return "retention time in seconds";
        break;
      case(std::int8_t)PtmPeptideListColumn::charge:
        return "peptide charge";
        break;
      case(std::int8_t)PtmPeptideListColumn::sequence:
        return "peptide sequence";
        break;
      case(std::int8_t)PtmPeptideListColumn::modifs:
        return "peptide modifications";
        break;
      case(std::int8_t)PtmPeptideListColumn::start:
        return "peptide start position on protein";
        break;
      case(std::int8_t)PtmPeptideListColumn::length:
        return "peptide length";
        break;
      case(std::int8_t)PtmPeptideListColumn::bestEvalue:
        return "best peptide Evalue";
        break;
      case(std::int8_t)PtmPeptideListColumn::theoretical_mhplus:
        return "peptide theoretical MH+";
        break;
      case(std::int8_t)PtmPeptideListColumn::delta_mhplus:
        return "peptide mass difference between observed mass and theoretical "
               "mass";
        break;
      case(std::int8_t)PtmPeptideListColumn::besthyperscore:
        return "best X!Tandem hyperscore";
      case(std::int8_t)PtmPeptideListColumn::bestposition:
        return "PTM positions of the top identified peptide (best Evalue) for "
               "this scan";
      case(std::int8_t)PtmPeptideListColumn::allobservedposition:
        return "all observed PTM positions for the same scan";
    }
  return "";
}

int
PtmPeptideTableModel::rowCount(const QModelIndex &parent [[maybe_unused]]) const
{
  qDebug() << "PtmPeptideTableModel::rowCount begin ";
  return _ptm_sample_scan_list.size();
}
int
PtmPeptideTableModel::columnCount(const QModelIndex &parent
                                  [[maybe_unused]]) const
{
  // qDebug() << "ProteinTableModel::columnCount begin ";
  return 15;
}
QVariant
PtmPeptideTableModel::headerData(int section,
                                 Qt::Orientation orientation,
                                 int role) const
{
  if(orientation == Qt::Horizontal)
    {
      switch(role)
        {
          case Qt::DisplayRole:
            return QVariant(getTitle(section));
            break;
          case Qt::ToolTipRole:
            return QVariant(getDescription(section));
            break;
        }
    }
  return QVariant();
}
QVariant
PtmPeptideTableModel::data(const QModelIndex &index, int role) const
{
  // generate a log message when this method gets called
  int row = index.row();
  int col = index.column();
  QStringList position_list;

  if(row >= (int)_ptm_sample_scan_list.size())
    return QVariant();
  switch(role)
    {
      case Qt::DisplayRole:
        switch(col)
          {

            case(std::int8_t)PtmPeptideListColumn::peptide_ptm_grouping_id:
              return QVariant(_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getGrpPeptideSp()
                                .get()
                                ->getGroupingId());
              break;
            case(std::int8_t)PtmPeptideListColumn::sample:
              return _ptm_sample_scan_list.at(row)
                .get()
                ->getRepresentativePeptideMatch()
                .getPeptideEvidence()
                ->getIdentificationDataSource()
                ->getSampleName();
              break;
            case(std::int8_t)PtmPeptideListColumn::scan:
              return QVariant((quint32)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getScanNumber());
              break;
            case(std::int8_t)PtmPeptideListColumn::rt:
              return QVariant((qreal)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getRetentionTime());
              break;
            case(std::int8_t)PtmPeptideListColumn::charge:
              return QVariant((quint32)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getCharge());
              break;
            case(std::int8_t)PtmPeptideListColumn::sequence:
              return QVariant::fromValue(_ptm_sample_scan_list.at(row).get());
              break;
            case(std::int8_t)PtmPeptideListColumn::modifs:
              return _ptm_sample_scan_list.at(row)
                .get()
                ->getRepresentativePeptideMatch()
                .getPeptideEvidence()
                ->getPeptideXtpSp()
                .get()
                ->getModifString();
              break;
            case(std::int8_t)PtmPeptideListColumn::start:
              return QVariant((quint32)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getStart() +
                              1);
              break;
            case(std::int8_t)PtmPeptideListColumn::length:
              return QVariant((quint32)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getPeptideXtpSp()
                                .get()
                                ->size());
              break;
            case(std::int8_t)PtmPeptideListColumn::bestEvalue:
              return QVariant((qreal)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getEvalue());
              break;
            case(std::int8_t)PtmPeptideListColumn::theoretical_mhplus:
              return QVariant((qreal)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getPeptideXtpSp()
                                .get()
                                ->getMz(1));
              break;
            case(std::int8_t)PtmPeptideListColumn::delta_mhplus:
              return QVariant((qreal)_ptm_sample_scan_list.at(row)
                                .get()
                                ->getRepresentativePeptideMatch()
                                .getPeptideEvidence()
                                ->getDeltaMass());
              break;
            case(std::int8_t)PtmPeptideListColumn::besthyperscore:
              return _ptm_sample_scan_list.at(row)
                .get()
                ->getRepresentativePeptideMatch()
                .getPeptideEvidence()
                ->getParam(PeptideEvidenceParam::tandem_hyperscore);
              break;
            case(std::int8_t)PtmPeptideListColumn::bestposition:
              for(unsigned int position :
                  _ptm_sample_scan_list.at(row).get()->getBestPtmPositionList(
                    _p_ptm_grouping_experiment))
                {
                  position_list << QString("%1").arg(position + 1);
                }
              return QVariant(position_list.join(" "));
              break;
            case(std::int8_t)PtmPeptideListColumn::allobservedposition:
              // return
              // _ptm_sample_scan_list.at(row).get()->getObservedPtmPositionList();
              for(unsigned int position :
                  _ptm_sample_scan_list.at(row)
                    .get()
                    ->getObservedPtmPositionList(_p_ptm_grouping_experiment))
                {
                  position_list << QString("%1").arg(position + 1);
                }
              return QVariant(position_list.join(" "));
              break;
          }
    }
  return QVariant();
}

void
PtmPeptideTableModel::setPtmIsland(
  const PtmGroupingExperiment *p_ptm_grouping_experiment, PtmIsland *ptm_island)
{
  qDebug() << "tmPeptideTableModel::setPtmIsland begin ";

  beginResetModel();
  _p_ptm_grouping_experiment = p_ptm_grouping_experiment;
  _p_ptm_island              = ptm_island;
  _ptm_sample_scan_list      = ptm_island->getPtmSampleScanSpList();
  // emit headerDataChanged(Qt::Horizontal, 0,11);
  // refresh();
  qDebug() << "tmPeptideTableModel::setPtmIsland end ";
  endResetModel();

  // this->_p_ptm_island_list_window->resizeColumnsToContents();
}
void
PtmPeptideTableModel::onPtmPeptideDataChanged()
{
  emit layoutAboutToBeChanged();
  emit layoutChanged();
}
