/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright(C) 2009,...,2018 Filippo Rusconi
 *
 * http://www.msxpertsuite.org
 *
 * This file is part of the msXpertSuite project.
 *
 * The msXpertSuite project is the successor of the massXpert project. This
 * project now includes various independent modules:
 *
 * - massXpert, model polymer chemistries and simulate mass spectrometric data;
 * - mineXpert, a powerful TIC chromatogram/mass spectrum viewer/miner;
 *
 * This program 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.
 *
 * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * END software license
 */


/////////////////////// Qt includes
#include <QApplication>


/////////////////////// Local includes
#include <massxpert/gui/MzLabOutputOligomerTableViewModel.hpp>
#include <massxpert/gui/MzLabOutputOligomerTableViewDlg.hpp>
#include <massxpert/nongui/globals.hpp>


namespace msXpSmassXpert
{

MzLabOutputOligomerTableViewModel::MzLabOutputOligomerTableViewModel(
  QList<OligomerPair *> *oligomerPairList, QObject *parent)
  : QAbstractTableModel(parent)
{
  QList<QVariant> rootData;

  if(!oligomerPairList)
    qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);

  mp_oligomerPairList = oligomerPairList;

  mp_parentDlg = static_cast<MzLabOutputOligomerTableViewDlg *>(parent);

  // Port to Qt5
  // reset();
}


MzLabOutputOligomerTableViewModel::~MzLabOutputOligomerTableViewModel()
{
}


void
MzLabOutputOligomerTableViewModel::setParentDlg(
  MzLabOutputOligomerTableViewDlg *dlg)
{
  mp_parentDlg = dlg;
}


MzLabOutputOligomerTableViewDlg *
MzLabOutputOligomerTableViewModel::parentDlg()
{
  return mp_parentDlg;
}


void
MzLabOutputOligomerTableViewModel::setMzLabWnd(MzLabWnd *wnd)
{
  mp_mzLabWnd = wnd;
}


MzLabWnd *
MzLabOutputOligomerTableViewModel::mzLabWnd()
{
  return mp_mzLabWnd;
}


void
MzLabOutputOligomerTableViewModel::setTableView(
  MzLabOutputOligomerTableView *tableView)
{
  if(!tableView)
    qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);

  mp_tableView = tableView;
}


MzLabOutputOligomerTableView *
MzLabOutputOligomerTableViewModel::tableView()
{
  return mp_tableView;
}


int
MzLabOutputOligomerTableViewModel::rowCount(const QModelIndex &parent) const
{
  Q_UNUSED(parent);

  return mp_oligomerPairList->size();
}


int
MzLabOutputOligomerTableViewModel::columnCount(const QModelIndex &parent) const
{
  Q_UNUSED(parent);

  return MZ_LAB_OUTPUT_OLIGO_TOTAL_COLUMNS;
}


QVariant
MzLabOutputOligomerTableViewModel::headerData(int section,
                                              Qt::Orientation orientation,
                                              int role) const
{
  if(role != Qt::DisplayRole)
    return QVariant();

  if(orientation == Qt::Vertical)
    {
      // Return the row number.
      QString valueString;
      valueString.setNum(section);
    }
  else if(orientation == Qt::Horizontal)
    {
      // Return the header of the column.
      switch(section)
        {
          case MZ_LAB_OUTPUT_OLIGO_1_MASS_COLUMN:
            return tr("m/z 1");
          case MZ_LAB_OUTPUT_OLIGO_1_CHARGE_COLUMN:
            return tr("z 1");
          case MZ_LAB_OUTPUT_OLIGO_2_MASS_COLUMN:
            return tr("m/z 2");
          case MZ_LAB_OUTPUT_OLIGO_2_CHARGE_COLUMN:
            return tr("z 2");
          case MZ_LAB_OUTPUT_OLIGO_ERROR_COLUMN:
            return tr("Error");
          case MZ_LAB_OUTPUT_OLIGO_MATCH_COLUMN:
            return tr("Match");
          default:
            qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);
        }
    }

  // Should never get here.
  return QVariant();
}


bool
MzLabOutputOligomerTableViewModel::setData(const QModelIndex &index,
                                           const QVariant &value,
                                           int role)
{
  // Fixme. Is it correct to not call anything here ?

  dataChanged(index, index);

  return true;
}


QVariant
MzLabOutputOligomerTableViewModel::data(const QModelIndex &index,
                                        int role) const
{
  if(!index.isValid())
    return QVariant();

  if(role == Qt::TextAlignmentRole)
    {
      return int(Qt::AlignRight | Qt::AlignVCenter);
    }
  else if(role == Qt::DisplayRole)
    {
      int row    = index.row();
      int column = index.column();

      // Let's get the data for the right column and the right
      // row. Let's find the row first, so that we get to the proper
      // oligomerPair.

      OligomerPair *oligomerPair = mp_oligomerPairList->at(row);

      // Now see what's the column that is asked for. Prepare a
      // string that we'll feed with the right data before returning
      // it as a QVariant.

      QString valueString;

      if(column == MZ_LAB_OUTPUT_OLIGO_1_MASS_COLUMN)
        {
          valueString.setNum(
            oligomerPair->mass1(), 'f', msXpS::OLIGOMER_DEC_PLACES);
        }
      else if(column == MZ_LAB_OUTPUT_OLIGO_1_CHARGE_COLUMN)
        {
          int charge = oligomerPair->charge1();

          valueString.setNum(charge);
        }
      else if(column == MZ_LAB_OUTPUT_OLIGO_2_MASS_COLUMN)
        {
          valueString.setNum(
            oligomerPair->mass2(), 'f', msXpS::OLIGOMER_DEC_PLACES);
        }
      else if(column == MZ_LAB_OUTPUT_OLIGO_2_CHARGE_COLUMN)
        {
          int charge = oligomerPair->charge2();

          valueString.setNum(charge);
        }
      else if(column == MZ_LAB_OUTPUT_OLIGO_ERROR_COLUMN)
        {
          valueString.setNum(
            oligomerPair->error(), 'f', msXpS::OLIGOMER_DEC_PLACES);
        }
      else if(column == MZ_LAB_OUTPUT_OLIGO_MATCH_COLUMN)
        {
          valueString =
            (oligomerPair->isMatching() ? QString("1") : QString("0"));
        }
      else
        {
          qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);
        }

      return valueString;
    }
  // End of
  // else if(role == Qt::DisplayRole)

  return QVariant();
}


void
MzLabOutputOligomerTableViewModel::addOligomerPair(OligomerPair *oligomerPair)
{
  if(!oligomerPair)
    qFatal("Fatal error at %s@%d. Aborting.", __FILE__, __LINE__);

  // We receive an oligomerPair which we are asked to add to the
  // list of oligomer pairs that we actually do not own, since they
  // are owned by the parent dialog window instance that is the
  // "owner" of this model. But since we want to add the oligomer
  // pair to the list of oligomer pairs belonging to that dialog
  // instance in such a way that the tableView takes it into
  // account, we have to do that addition work here.

  // Note that we are acutally *transferring* the oligomer to this
  // model's mp_oligomerPairList.

  int oligomerPairCount = mp_oligomerPairList->size();

  // qDebug() << __FILE__ << __LINE__
  //          << "model oligomer pairs:" << oligomerPairCount;

  int oligomerPairsToAdd = 1;

  // qDebug() << __FILE__ << __LINE__
  //          << "oligomer pairs to add:" << oligomerPairsToAdd;

  int addedOligomerPairCount = 0;

  // We have to let know the model that we are going to modify the
  // list of oligomer pairs and thus the number of rows in the table
  // view. We will append the oligomer pair to the preexisting ones,
  // which means we are going to have our appended oligomer pair at
  // index=oligomerPairCount.

  beginInsertRows(QModelIndex(),
                  oligomerPairCount,
                  (oligomerPairCount + oligomerPairsToAdd - 1));

  for(int iter = 0; iter < oligomerPairsToAdd; ++iter)
    {
      mp_oligomerPairList->append(oligomerPair);

      ++addedOligomerPairCount;
    }

  endInsertRows();

  return;
}


} // namespace msXpSmassXpert
