/* BEGIN software license
 *
 * msXpertSuite - mass spectrometry software suite
 * -----------------------------------------------
 * Copyright (C) 2009--2020 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 <QtGlobal>
#include <QDebug>

/////////////////////// Local includes
#include "Ponderable.hpp"


namespace msxps
{
namespace minexpert
{

Ponderable::Ponderable(double mono, double avg)
{
  m_mono = mono;
  m_avg  = avg;
}


Ponderable::Ponderable(const Ponderable &other)
  : m_mono(other.m_mono), m_avg(other.m_avg)
{
}


Ponderable::~Ponderable()
{
}


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

  return other;
}


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

  if(other == this)
    return;

  other->m_mono = m_mono;
  other->m_avg  = m_avg;
}


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

  m_mono = other.m_mono;
  m_avg  = other.m_avg;
}


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

  return *this;
}


void
Ponderable::setMasses(double mono, double avg)
{
  m_mono = mono;
  m_avg  = avg;
}


void
Ponderable::setMass(double mass, MassType type)
{
  if(type & MassType::MASS_MONO)
    m_mono = mass;
  else if(type & MassType::MASS_AVG)
    m_avg = mass;

  return;
}


void
Ponderable::incrementMass(double mass, MassType type)
{
  if(type & MassType::MASS_MONO)
    m_mono += mass;
  else if(type & MassType::MASS_AVG)
    m_avg += mass;

  return;
}


void
Ponderable::masses(double *mono, double *avg) const
{
  Q_ASSERT(mono && avg);

  *mono = m_mono;
  *avg  = m_avg;
}


double
Ponderable::mass(MassType type) const
{
  if(type == MassType::MASS_MONO)
    return m_mono;

  return m_avg;
}


void
Ponderable::clearMasses()
{
  m_mono = 0.0;
  m_avg  = 0.0;
}


void
Ponderable::setMono(double mass)
{
  m_mono = mass;
}


bool
Ponderable::setMono(const QString &mass)
{
  bool ok = false;

  double value = mass.toDouble(&ok);

  if(!ok)
    return false;

  m_mono = value;

  return true;
}


void
Ponderable::incrementMono(double mass)
{
  m_mono += mass;
}


void
Ponderable::decrementMono(double mass)
{
  m_mono -= mass;
}


double
Ponderable::mono() const
{
  return m_mono;
}


double &
Ponderable::rmono()
{
  return m_mono;
}


QString
Ponderable::monoString(int decimalPlaces) const
{
  if(decimalPlaces < 0)
    decimalPlaces = 0;

  QString mass;
  mass.setNum(m_mono, 'f', decimalPlaces);

  return mass;
}


void
Ponderable::setAvg(double mass)
{
  m_avg = mass;
}


bool
Ponderable::setAvg(const QString &mass)
{
  bool ok = false;

  double value = mass.toDouble(&ok);

  if(!ok)
    return false;

  m_avg = value;

  return true;
}


void
Ponderable::incrementAvg(double mass)
{
  m_avg += mass;
}


void
Ponderable::decrementAvg(double mass)
{
  m_avg -= mass;
}


double
Ponderable::avg() const
{
  return m_avg;
}


double &
Ponderable::ravg()
{
  return m_avg;
}


QString
Ponderable::avgString(int decimalPlaces) const
{
  if(decimalPlaces < 0)
    decimalPlaces = 0;

  QString mass;
  mass.setNum(m_avg, 'f', decimalPlaces);

  return mass;
}


bool
Ponderable::operator==(const Ponderable &other) const
{
  if(m_mono == other.m_mono && m_avg == other.m_avg)
    return true;

  return false;
}


bool
Ponderable::operator!=(const Ponderable &other) const
{
  if(m_mono != other.m_mono || m_avg != other.m_avg)
    {
      // qDebug() << << "m_mono:" << m_mono
      //          << "/"
      //          << "other.m_mono:" << other.m_mono
      //          << "--"
      //          << "m_avg:" << m_avg
      //          << "/"
      //          << "other.m_avg:" << other.m_avg;

      return true;
    }

  return false;
}


bool
Ponderable::calculateMasses()
{
  return true;
}


bool
Ponderable::accountMasses(double *mono, double *avg, int times) const
{
  if(mono)
    *mono += m_mono * times;

  if(avg)
    *avg += m_avg * times;

  return true;
}

} // namespace minexpert

} // namespace msxps
