/* massXpert - the true massist's program.
   --------------------------------------
   Copyright(C) 2006,2007 Filippo Rusconi

   http://www.massxpert.org/massXpert

   This file is part of the massXpert project.

   The massxpert project is the successor to the "GNU polyxmass"
   project that is an official GNU project package(see
   www.gnu.org). The massXpert project is not endorsed by the GNU
   project, although it is released ---in its entirety--- under the
   GNU General Public License. A huge part of the code in massXpert
   is actually a C++ rewrite of code in GNU polyxmass. As such
   massXpert was started at the Centre National de la Recherche
   Scientifique(FRANCE), that granted me the formal authorization to
   publish it under this Free Software License.

   This software is free software; you can redistribute it and/or
   modify it under the terms of the GNU  General Public
   License version 3, as published by the Free Software Foundation.
   

   This software 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 software; if not, write to the

   Free Software Foundation, Inc.,

   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/


/////////////////////// Local includes
#include "mzLabOutputOligomerTableViewModel.hpp"
#include "mzLabOutputOligomerTableViewDlg.hpp"
#include "globals.hpp"
#include "application.hpp"


namespace massXpert
{

  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)
      {
        Application *application = static_cast<Application *>(qApp);
        QLocale locale = application->locale();

        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 =
              locale.toString(oligomerPair->mass1(), 'f',
                              MXP_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 =
              locale.toString(oligomerPair->mass2(), 'f',
                              MXP_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 =
              locale.toString(oligomerPair->error(), 'f',
                              MXP_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 massXpert
