/* 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>
#include <QRegularExpressionMatch>


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


namespace msXpSlibmass
{

int dataPointMetaTypeId =
  qRegisterMetaType<msXpSlibmass::DataPoint>("msXpSlibmass::DataPoint");


//! Default constructor.
/*!

  \c m_key and \c m_val are initialized to qSNaN(), which makes it easy to
  validate.

*/
DataPoint::DataPoint()
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
  //<< "default constructor, instance:" << this;
}


//! Constructor.
/*!

  Initialize the member data with the parameters.

  \param key copied to \c m_key
  \param val copied to \c m_val

*/
DataPoint::DataPoint(double key, double val)
{

  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "(double key, double
  // //val)"
  //<< "key,val initializing constructor this:" << this;

  m_key = key;
  m_val = val;
}


//! Copy constructor.
/*!

  Constructs \c this to be identical to \p other.

*/
DataPoint::DataPoint(const DataPoint &other)
{

  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "(const DataPoint
  // &other)"
  //<< "copy constructor, other :" << &other << "this:" << this;

  m_key = other.m_key;
  m_val = other.m_val;
}


//! Constructor.
/*!

  Construct \c this by initializing its member values from their string
  representation in \p xyLine.

  \p xyLine is a line of text having the following generic format:
  <number1><non-number><number2>, with <number1> a string representation of key,
  <non-number> any string element that is not a number and <number2> a string
  representation of val. The decomposition of xyLine into key and val values is
  performed using initialize(const QString &xyLine);

  \sa bool initialize(const QString &xyLine).

*/
DataPoint::DataPoint(const QString &xyLine)
{

  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "() initializing with
  // xyLine";

  initialize(xyLine);
}


//! Destructor.
DataPoint::~DataPoint()
{
  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__ << "()"
  //<< "Destructing DataPoint:" << this;
}


//! Assignment operator.
/*!

  The assignment operator explicitely copies the member data from \p other
  into \c this DataPoint instance.

*/
DataPoint &
DataPoint::operator=(const DataPoint &other)
{
  if(&other == this)
    return *this;

  // qDebug() << __FILE__ << __LINE__ << __FUNCTION__
  //<< "this:" << this << "other:" << &other;

  m_key = other.m_key;
  m_val = other.m_val;

  return *this;
}


//! Initialize \c this DataPoint instance using a string representation of a
//! (key, val) pair in \p xyLine.
/*!

  \p xyLine is a line of text having the following generic format:
  <number1><non-number><number2>, with <number1> a string representation of
  key, <non-number> any string element that is not a number and <number2> a
  string representation of val. The decomposition of xyLine into key and val
  values is performed using initialize(const QString &xyLine);

*/
bool
DataPoint::initialize(const QString &xyLine)
{
  // qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()";

  // Initialize to NaN to start with.
  m_key = qSNaN();
  m_val = qSNaN();

  QRegularExpressionMatch regExpMatch;

  regExpMatch = msXpS::gXyFormatMassDataRegExp.match(xyLine);

  if(!regExpMatch.hasMatch())
    return false;

  bool ok = false;

  double key = regExpMatch.captured(1).toDouble(&ok);

  if(!ok)
    return false;

  // Note that group 2 is the separator group.

  double val = regExpMatch.captured(3).toDouble(&ok);

  if(!ok)
    return false;

  m_key = key;
  m_val = val;

  return true;
}


//! Initialize \c this DataPoint instance using a key/value pair.
void
DataPoint::initialize(const DataPoint &dataPoint)
{
  m_key = dataPoint.m_key;
  m_val = dataPoint.m_val;
}


//! Initialize \c this DataPoint instance using a key/value pair.
void
DataPoint::initialize(double key, double value)
{
  m_key = key;
  m_val = value;
}


//! Set the \c m_key value.
/*!
 */
void
DataPoint::setKey(double key)
{
  m_key = key;
}


//! Get the \c m_key value.
/*!

  \return \c m_key.

*/
double
DataPoint::key() const
{
  return m_key;
}


//! Set the \c m_val value.
/*!
 */
void
DataPoint::setVal(double value)
{
  m_val = value;
}


//! Get the \c m_val value.
/*!

  \return \c m_val.

*/
double
DataPoint::val() const
{
  return m_val;
}


//! Get a <em> non-const reference</em> to \c m_val.
/*!

  \return a <em> non-const reference</em> to \c m_val.

*/
double &
DataPoint::rval()
{
  return m_val;
}


//! Tells if \c this DataPoint instance is valid.
/*!

  A DataPoint is valid if both \c m_key and \c m_val members are not NaN.

  \return true if the DataPoint is valid, false otherwise.
  */
bool
DataPoint::isValid() const
{
  return (!qIsNaN(m_key) && !qIsNaN(m_val));
}


} // namespace msXpSlibmass
