/* 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 <QDebug>


/////////////////////// Local includes
#include "MassSearchOligomerTableViewModel.hpp"
#include "MassSearchOligomerTableViewSortProxyModel.hpp"


namespace MsXpS
{

namespace massxpert
{


  MassSearchOligomerTableViewSortProxyModel::
    MassSearchOligomerTableViewSortProxyModel(QObject *parent)
    : QSortFilterProxyModel(parent)
  {
  }


  MassSearchOligomerTableViewSortProxyModel::
    ~MassSearchOligomerTableViewSortProxyModel()
  {
  }


  void
  MassSearchOligomerTableViewSortProxyModel::setSearchedFilter(double value)
  {
    m_searchedFilter = value;
  }


  void
  MassSearchOligomerTableViewSortProxyModel::setErrorFilter(double value)
  {
    m_errorFilter = value;
  }


  void
  MassSearchOligomerTableViewSortProxyModel::setMonoFilter(double value)
  {
    m_monoFilter = value;
  }


  void
  MassSearchOligomerTableViewSortProxyModel::setAvgFilter(double value)
  {
    m_avgFilter = value;
  }


  void
  MassSearchOligomerTableViewSortProxyModel::setTolerance(double value)
  {
    m_tolerance = value;
  }


  bool
  MassSearchOligomerTableViewSortProxyModel::lessThan(
    const QModelIndex &left, const QModelIndex &right) const
  {
    QVariant leftData  = sourceModel()->data(left);
    QVariant rightData = sourceModel()->data(right);

    if(leftData.typeId() == QMetaType::Int)
      {
        // The Partial column

        int leftValue  = leftData.toInt();
        int rightValue = rightData.toInt();

        return (leftValue < rightValue);
      }
    if(leftData.typeId() == QMetaType::Bool)
      {
        // The libXpertMass::Modif column

        int leftValue  = leftData.toInt();
        int rightValue = rightData.toInt();

        return (leftValue < rightValue);
      }
    else if(leftData.typeId() == QMetaType::QString &&
            (left.column() == MASS_SEARCH_OLIGO_SEARCHED_COLUMN ||
             left.column() == MASS_SEARCH_OLIGO_ERROR_COLUMN ||
             left.column() == MASS_SEARCH_OLIGO_MONO_COLUMN ||
             left.column() == MASS_SEARCH_OLIGO_AVG_COLUMN))
      {
        bool ok = false;

        double leftValue = leftData.toDouble(&ok);
        Q_ASSERT(ok);
        double rightValue = rightData.toDouble(&ok);
        Q_ASSERT(ok);

        return (leftValue < rightValue);
      }

    if(leftData.typeId() == QMetaType::QString)
      {
        QString leftString  = leftData.toString();
        QString rightString = rightData.toString();

        if(!leftString.isEmpty() && leftString.at(0) == '[')
          return sortCoordinates(leftString, rightString);
        else if(!leftString.isEmpty() && leftString.contains('#'))
          return sortName(leftString, rightString);
        else
          return (QString::localeAwareCompare(leftString, rightString) < 0);
      }


    return true;
  }


  bool
  MassSearchOligomerTableViewSortProxyModel::sortCoordinates(
    QString left, QString right) const
  {
    QString local = left;

    local.remove(0, 1);
    local.remove(local.size() - 1, 1);

    int dash = local.indexOf('-');

    QString leftStartStr = local.left(dash);

    bool ok          = false;
    int leftStartInt = leftStartStr.toInt(&ok);

    local.remove(0, dash + 1);

    QString leftEndStr = local;

    ok             = false;
    int leftEndInt = leftEndStr.toInt(&ok);

    //    qDebug() << "left coordinates" << leftStartInt << "--" << leftEndInt;

    local = right;

    local.remove(0, 1);
    local.remove(local.size() - 1, 1);

    dash = local.indexOf('-');

    QString rightStartStr = local.left(dash);

    ok                = false;
    int rightStartInt = rightStartStr.toInt(&ok);

    local.remove(0, dash + 1);

    QString rightEndStr = local;

    ok              = false;
    int rightEndInt = rightEndStr.toInt(&ok);

    //    qDebug() << "right coordinates" << rightStartInt << "--" <<
    //    rightEndInt;


    if(leftStartInt < rightStartInt)
      return true;

    if(leftEndInt < rightEndInt)
      return true;

    return false;
  }


  bool
  MassSearchOligomerTableViewSortProxyModel::sortName(QString left,
                                                      QString right) const
  {
    QString local = left;


    int diesis = local.indexOf('#');

    QString leftPartialStr = local.left(diesis);

    bool ok            = false;
    int leftPartialInt = leftPartialStr.toInt(&ok);

    local.remove(0, diesis + 1);

    QString leftOligoStr = local;

    ok               = false;
    int leftOligoInt = leftOligoStr.toInt(&ok);

    //    qDebug() << "left: partial#oligo"
    // 	     << leftPartialInt << "#" << leftOligoInt;

    local = right;

    diesis = local.indexOf('#');

    QString rightPartialStr = local.left(diesis);

    ok                  = false;
    int rightPartialInt = rightPartialStr.toInt(&ok);

    local.remove(0, diesis + 1);

    QString rightOligoStr = local;

    ok                = false;
    int rightOligoInt = rightOligoStr.toInt(&ok);

    //    qDebug() << "right: partial#oligo"
    // 	     << rightPartialInt << "#" << rightOligoInt;

    if(leftPartialInt < rightPartialInt)
      return true;

    if(leftOligoInt < rightOligoInt)
      return true;

    return false;
  }


  bool
  MassSearchOligomerTableViewSortProxyModel::filterAcceptsRow(
    int sourceRow, const QModelIndex &sourceParent) const
  {
    int filterKeyColumnIndex = filterKeyColumn();

    if(filterKeyColumnIndex == MASS_SEARCH_OLIGO_SEARCHED_COLUMN)
      {
        // The column of the searched mass.
        QModelIndex index = sourceModel()->index(
          sourceRow, MASS_SEARCH_OLIGO_SEARCHED_COLUMN, sourceParent);

        bool ok = false;

        QVariant data = sourceModel()->data(index);

        double searched = data.toDouble(&ok);
        Q_ASSERT(ok);

        if(m_searchedFilter == searched)
          return true;
        else
          return false;
      }
    else if(filterKeyColumnIndex == MASS_SEARCH_OLIGO_ERROR_COLUMN)
      {
        // The column of the error.
        QModelIndex index = sourceModel()->index(
          sourceRow, MASS_SEARCH_OLIGO_ERROR_COLUMN, sourceParent);

        bool ok = false;

        QVariant data = sourceModel()->data(index);

        double error = data.toDouble(&ok);
        Q_ASSERT(ok);

        double left  = m_errorFilter - m_tolerance;
        double right = m_errorFilter + m_tolerance;

        if(left <= error && error <= right)
          return true;
        else
          return false;
      }
    else if(filterKeyColumnIndex == MASS_SEARCH_OLIGO_MONO_COLUMN)
      {
        // The column of the mono mass.
        QModelIndex index = sourceModel()->index(
          sourceRow, MASS_SEARCH_OLIGO_MONO_COLUMN, sourceParent);

        bool ok = false;

        QVariant data = sourceModel()->data(index);

        double mass = data.toDouble(&ok);
        Q_ASSERT(ok);

        double left  = m_monoFilter - m_tolerance;
        double right = m_monoFilter + m_tolerance;

        if(left <= mass && mass <= right)
          return true;
        else
          return false;
      }
    else if(filterKeyColumnIndex == MASS_SEARCH_OLIGO_AVG_COLUMN)
      {
        // The column of the avg mass.
        QModelIndex index = sourceModel()->index(
          sourceRow, MASS_SEARCH_OLIGO_AVG_COLUMN, sourceParent);

        bool ok = false;

        QVariant data = sourceModel()->data(index);

        double mass = data.toDouble(&ok);
        Q_ASSERT(ok);

        double left  = m_avgFilter - m_tolerance;
        double right = m_avgFilter + m_tolerance;

        if(left <= mass && mass <= right)
          return true;
        else
          return false;
      }

    return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
  }


  void
  MassSearchOligomerTableViewSortProxyModel::applyNewFilter()
  {
    invalidateFilter();
  }

} // namespace massxpert

} // namespace MsXpS
