/**
 * \file gui/ptm_island_list_window/ptmislandtablemodel.h
 * \date 30/5/2017
 * \author Olivier Langella
 * \brief display all ptm islands
 */

/*******************************************************************************
 * 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 "ptmislandtablemodel.h"
#include "ptmislandlistwindow.h"


PtmIslandTableModel::PtmIslandTableModel(
  PtmIslandListWindow *p_ptm_island_list_window)
{
  _p_ptm_island_list_window = p_ptm_island_list_window;
}

PtmIslandTableModel::~PtmIslandTableModel()
{
}

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

PtmIslandListColumn
PtmIslandTableModel::getPtmIslandListColumn(std::int8_t column)
{
  return static_cast<PtmIslandListColumn>(column);
}

const QString
PtmIslandTableModel::getTitle(std::int8_t column)
{
  switch(column)
    {
      case(std::int8_t)PtmIslandListColumn::checked:
        return "Checked";
        break;
      case(std::int8_t)PtmIslandListColumn::spectrum:
        return "spectrum";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_spectrum:
        return "PTM spectrum";
        break;
      case(std::int8_t)PtmIslandListColumn::description:
        return "description";
        break;
      case(std::int8_t)PtmIslandListColumn::multiptm:
        return "multi PTM";
        break;
      case(std::int8_t)PtmIslandListColumn::sequence:
        return "sequence";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_island_id:
        return "PTM island ID";
        break;
      case(std::int8_t)PtmIslandListColumn::accession:
        return "accession";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_position_list:
        return "ptm positions";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_island_start:
        return "start";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_island_length:
        return "length";
    }
  return "";
}

const QString
PtmIslandTableModel::getDescription(std::int8_t column)
{
  switch(column)
    {
      case(std::int8_t)PtmIslandListColumn::checked:
        return "Checked PTM";
        break;
      case(std::int8_t)PtmIslandListColumn::spectrum:
        return "number of distinct spectrum assigned to this PTM island";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_spectrum:
        return "number of distinct spectrum wearing a PTM";
        break;
      case(std::int8_t)PtmIslandListColumn::description:
        return "protein description";
        break;
      case(std::int8_t)PtmIslandListColumn::multiptm:
        return "number of distinct spectrum containing more than 1 ptm";
        break;
      case(std::int8_t)PtmIslandListColumn::sequence:
        return "number of unique peptide sequence";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_island_id:
        return "unique PTM island identifier";
        break;
      case(std::int8_t)PtmIslandListColumn::accession:
        return "protein accession";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_position_list:
        return "PTM positions observed in this PTM island";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_island_start:
        return "PTM island start on the protein";
        break;
      case(std::int8_t)PtmIslandListColumn::ptm_island_length:
        return "PTM island length";
    }
  return "";
}
void
PtmIslandTableModel::setIdentificationGroup(
  IdentificationGroup *p_identification_group)
{
  qDebug() << "PtmIslandTableModel::setIdentificationGroup begin ";

  beginResetModel();
  _p_identification_group = p_identification_group;

  // emit headerDataChanged(Qt::Horizontal, 0,11);
  // refresh();
  qDebug() << "PtmIslandTableModel::setIdentificationGroup end ";
  endResetModel();

  this->_p_ptm_island_list_window->resizeColumnsToContents();
}

IdentificationGroup *
PtmIslandTableModel::getIdentificationGroup()
{
  return _p_identification_group;
}

const PtmGroupingExperiment *
PtmIslandTableModel::getPtmGroupingExperiment() const
{
  if(_p_identification_group == nullptr)
    {
      return nullptr;
    }
  return _p_identification_group->getPtmGroupingExperiment();
}
int
PtmIslandTableModel::rowCount(const QModelIndex &parent [[maybe_unused]]) const
{
  // qDebug() << "PtmIslandTableModel::rowCount begin ";
  if(getPtmGroupingExperiment() != nullptr)
    {
      // qDebug() << "PtmIslandTableModel::rowCount(const QModelIndex &parent )
      // " << getPtmGroupingExperiment()->getPtmIslandList().size();
      return (int)getPtmGroupingExperiment()->getPtmIslandList().size();
    }
  return 0;
}
int
PtmIslandTableModel::columnCount(const QModelIndex &parent
                                 [[maybe_unused]]) const
{
  // qDebug() << "ProteinTableModel::columnCount begin ";
  if(getPtmGroupingExperiment() != nullptr)
    {
      return (std::int8_t)PtmIslandListColumn::last;
    }
  return 0;
}
QVariant
PtmIslandTableModel::headerData(int section,
                                Qt::Orientation orientation,
                                int role) const
{
  if(getPtmGroupingExperiment() == nullptr)
    return QVariant();
  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
PtmIslandTableModel::data(const QModelIndex &index, int role) const
{
  // generate a log message when this method gets called
  if(getPtmGroupingExperiment() == nullptr)
    return QVariant();
  int row = index.row();
  int col = index.column();
  switch(role)
    {
      case Qt::CheckStateRole:
        if(col == (std::int8_t)
                    PtmIslandListColumn::checked) // add a checkbox to cell(1,0)
          {
            if(getPtmGroupingExperiment()
                 ->getPtmIslandList()
                 .at(row)
                 ->isChecked())
              {
                return Qt::Checked;
              }
            else
              {
                return Qt::Unchecked;
              }
          }
        break;
      case Qt::SizeHintRole:
        // qDebug() << "ProteinTableModel::headerData " <<
        // ProteinTableModel::getColumnWidth(section);
        return QSize(PtmIslandTableModel::getColumnWidth(col), 30);
        break;
      case Qt::DisplayRole:
        if(_p_identification_group == nullptr)
          {
            return QVariant();
          }
        switch(col)
          {
            case(std::int8_t)PtmIslandListColumn::checked:
              return QVariant();
              break;
            case(std::int8_t)PtmIslandListColumn::spectrum:
              return QVariant((quint64)getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->getPtmIslandSubroup()
                                ->countSampleScan());
              break;
            case(std::int8_t)PtmIslandListColumn::ptm_spectrum:
              return QVariant(
                (quint64)getPtmGroupingExperiment()
                  ->getPtmIslandList()
                  .at(row)
                  .get()
                  ->countSampleScanWithPtm(getPtmGroupingExperiment()));
              break;
            case(std::int8_t)PtmIslandListColumn::description:
              return QVariant(getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->getProteinMatch()
                                ->getProteinXtpSp()
                                .get()
                                ->getDescription());
              break;
            case(std::int8_t)PtmIslandListColumn::multiptm:
              return QVariant(
                (quint64)getPtmGroupingExperiment()
                  ->getPtmIslandList()
                  .at(row)
                  .get()
                  ->countSampleScanMultiPtm(getPtmGroupingExperiment()));
              break;
            case(std::int8_t)PtmIslandListColumn::sequence:
              return QVariant((quint64)getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->countSequence());
              break;
            case(std::int8_t)PtmIslandListColumn::ptm_island_id:
              return QVariant(getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->getGroupingId());
              break;
            case(std::int8_t)PtmIslandListColumn::accession:
              return QVariant(getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->getProteinMatch()
                                ->getProteinXtpSp()
                                .get()
                                ->getAccession());
              break;
            case(std::int8_t)PtmIslandListColumn::ptm_island_start:
              return QVariant(getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->getStart() +
                              1);
              break;
            case(std::int8_t)PtmIslandListColumn::ptm_island_length:
              return QVariant(getPtmGroupingExperiment()
                                ->getPtmIslandList()
                                .at(row)
                                .get()
                                ->size());
              break;
            case(std::int8_t)PtmIslandListColumn::ptm_position_list:
              QStringList position_list;
              for(unsigned int position : getPtmGroupingExperiment()
                                            ->getPtmIslandList()
                                            .at(row)
                                            .get()
                                            ->getPositionList())
                {
                  position_list << QString("%1").arg(position + 1);
                }
              return QVariant(position_list.join(" "));
          }
    }
  return QVariant();
}


void
PtmIslandTableModel::onPtmIslandDataChanged()
{
  qDebug() << "PtmIslandTableModel::onPtmIslandDataChanged begin "
           << rowCount();
  emit layoutAboutToBeChanged();
  emit layoutChanged();
}

int
PtmIslandTableModel::getColumnWidth(int column)
{
  qDebug() << "PtmIslandTableModel::getColumnWidth " << column;
  switch(column)
    {
      case(int)PtmIslandListColumn::checked:
        break;
      case(int)PtmIslandListColumn::accession:
        qDebug() << "PtmIslandTableModel::getColumnWidth accession " << column;
        return 250;
        break;
      case(int)PtmIslandListColumn::description:
        return 400;
        break;
    }
  return 100;
}
