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


/////////////////////// Local includes
#include <globals/globals.hpp>
#include <libmass/MassList.hpp>


namespace msXpSlibmass
{

MassList::MassList(QString name)
{
  m_name = name;
}


MassList::MassList(QString name, const QString &text)
{
  m_name     = name;
  m_massText = text;
}


MassList::MassList(QString name, const QStringList &stringList)
{
  m_name = name;

  if(!stringList.isEmpty())
    m_massStringList = stringList;
}


MassList::MassList(QString name, const QList<double> &doubleList)
{
  m_name = name;

  QListIterator<double> iter(doubleList);

  while(iter.hasNext())
    {
      m_massList.append(iter.next());
    }
}


MassList::~MassList()
{
}


MassList::MassList(const MassList &other)
  : m_name(other.m_name),
    m_comment(other.m_comment),
    m_massText(other.m_massText),
    m_massStringList(other.m_massStringList)
{
  QListIterator<double> iter(other.m_massList);

  while(iter.hasNext())
    {
      m_massList.append(iter.next());
    }
}


MassList *
MassList::clone() const
{
  MassList *other = new MassList(*this);

  return other;
}


void
MassList::clone(MassList *other) const
{
  Q_ASSERT(other);

  if(other == this)
    return;

  other->m_name    = m_name;
  other->m_comment = m_comment;

  other->m_massText       = m_massText;
  other->m_massStringList = m_massStringList;

  other->m_massList.clear();

  QListIterator<double> iter(m_massList);

  while(iter.hasNext())
    {
      other->m_massList.append(iter.next());
    }
}


void
MassList::mold(const MassList &other)
{
  if(&other == this)
    return;

  m_name    = other.m_name;
  m_comment = other.m_comment;

  m_massText       = other.m_massText;
  m_massStringList = other.m_massStringList;

  m_massList.clear();

  QListIterator<double> iter(other.m_massList);

  while(iter.hasNext())
    {
      m_massList.append(iter.next());
    }
}


MassList &
MassList::operator=(const MassList &other)
{
  if(&other != this)
    mold(other);

  return *this;
}


//! Sets the name.
/*!  \param name new name.
 */
void
MassList::setName(QString name)
{
  if(!name.isEmpty())
    m_name = name;
}


QString
MassList::name()
{
  return m_name;
}


//! Sets the comment.
/*!  \param comment new comment.
 */
void
MassList::setComment(QString comment)
{
  if(!comment.isEmpty())
    m_comment = comment;
}


const QString &
MassList::comment() const
{
  return m_comment;
}


int
MassList::size() const
{
  return m_massList.size();
}


const QList<double> &
MassList::massList() const
{
  return m_massList;
}


double
MassList::at(int index) const
{
  Q_ASSERT(index >= 0 && index < m_massList.size());

  return m_massList.at(index);
}


const QString &
MassList::massText() const
{
  return m_massText;
}


int
MassList::makeMassList()
{
  if(m_massText.isEmpty())
    return 0;

  QStringList errorList;

  m_massStringList = m_massText.split(QRegExp("\n"), QString::SkipEmptyParts);

  for(int iter = 0; iter < m_massStringList.size(); ++iter)
    {
      bool ok = false;

      double value = m_massStringList.at(iter).toDouble(&ok);

      if(!value && !ok)
        {
          errorList.append(m_massStringList.at(iter));
        }

      m_massList.append(value);
    }

  // Because there was text, if an error occurred, then output the
  // error list and return -1.

  if(!errorList.isEmpty())
    {
      qDebug() << __FILE__ << __LINE__ << "Error list:" << errorList;

      return -1;
    }
  else
    return m_massList.size();
}


int
MassList::makeMassText()
{
  m_massText.clear();

  for(int iter = 0; iter < m_massList.size(); ++iter)
    {
      QString mass;
      mass.setNum(m_massList.at(iter), 'f', msXpS::OLIGOMER_DEC_PLACES);

      m_massText.append(mass + "\n");
    }

  return m_massText.size();
}


void
MassList::sortAscending()
{
  qSort(m_massList.begin(), m_massList.end());
}


void
MassList::sortDescending()
{
  qSort(m_massList.begin(), m_massList.end(), qGreater<double>());
}


void
MassList::applyMass(double mass)
{
  for(int iter = 0; iter < m_massList.size(); ++iter)
    {
      double value = m_massList.at(iter) + mass;

      m_massList.replace(iter, value);
    }
}


void
MassList::removeLessThan(double mass)
{
  QMutableListIterator<double> iter(m_massList);

  while(iter.hasNext())
    {
      double value = iter.next();
      if(value < mass)
        {
          iter.remove();
        }
    }
}

} // namespace msXpSlibmass
