/**
 * \file pappsomspp/mass_range.cpp
 * \date 4/3/2015
 * \author Olivier Langella
 * \brief object to handle a mass range (an mz value + or - some delta)
 */

/*******************************************************************************
 * Copyright (c) 2015 Olivier Langella <Olivier.Langella@moulon.inra.fr>.
 *
 * This file is part of the PAPPSOms++ library.
 *
 *     PAPPSOms++ 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.
 *
 *     PAPPSOms++ 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 PAPPSOms++.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <Olivier.Langella@moulon.inra.fr> - initial API and
 *implementation
 ******************************************************************************/

#include "mzrange.h"
#include "exception/exceptionnotpossible.h"
#include <QStringList>
#include <cmath>
#include <QDebug>


namespace pappso
{

/// Constructs MzRange object using 1 precision (the same for lower or upper
/// range).
MzRange::MzRange(pappso_double mz, PrecisionPtr precision)
  : m_mz(mz), m_delta(precision->delta(m_mz))
{
}


//! Construct a MzRange object with \p mz and \p delta
/*!
 *
 * \p delta should be construed as the whole tolerance such that \c lower()
 * returns \c m_mz - \c m_delta and \c upper() returns \c m_mz + \c m_delta.
 *
 */
MzRange::MzRange(pappso_double mz, pappso_double delta)
  : m_mz(mz), m_delta(delta)
{
}


/// Constructs MzRange object using 2 different precisions: lower and upper.
MzRange::MzRange(pappso_double mz,
                 PrecisionPtr precision_lower,
                 PrecisionPtr precision_upper)
{

  m_delta = (precision_lower->delta(mz) + precision_upper->delta(mz)) / 2;
  m_mz    = mz - precision_lower->delta(mz) + m_delta;
}


MzRange::MzRange(const MzRange &other)
  : m_mz(other.m_mz), m_delta(other.m_delta)
{
  // std::cout << "MzRange::MzRange (const MzRange & other)" << std::endl;
}


MzRange::~MzRange()
{
}


MzRange &
MzRange::operator=(const MzRange &other)
{
  m_mz    = other.m_mz;
  m_delta = other.m_delta;

  return *this;
}


MzRange &
MzRange::operator+=(const MzRange &other)
{
  m_mz += other.m_mz;
  m_delta += other.m_delta;

  return *this;
}

MzRange &
MzRange::operator*=(double number)
{
  m_mz *= number;
  m_delta *= number;

  return *this;
}

pappso_double
MzRange::getMz() const
{
  return m_mz;
}

bool
MzRange::contains(pappso_double mz) const
{
  // qDebug() << " " << std::abs(mz - m_mz)  << " m_delta:" << m_delta;
  if(std::abs(mz - m_mz) <= m_delta)
    {
      return true;
    }
  return false;
}

QString
MzRange::toString() const
{
  // QString s = "mz=" + QString::number(m_mz) + " delta=" +
  // QString::number(m_delta);
  return QString("mz=%1 delta=%2 : %3 < %4 < %5")
    .arg(m_mz)
    .arg(m_delta)
    .arg(lower())
    .arg(m_mz)
    .arg(upper());
}

} // namespace pappso
