/* 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 <QChar>
#include <QDebug>
#include <QString>


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


namespace MsXpS
{

namespace libXpertMass
{


/*!
\class MsXpS::libXpertMass::CalcOptions
\inmodule libXpertMass
\ingroup XpertMassMassCalculations
\inheaderfile CalcOptions.hpp

\brief The CalcOptions class provides the specifications that
configure the way masses are calculated for \l{Oligomer}s, \l{Polymer}s and
product ions.
*/

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_deepCalculation

  \brief Tells if  the calculations must involve the recalculation of all
the masses of the \l{Monomer}s in the sequence.
  */

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_coordinateList

  \brief The list of Coordinates.
  */

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_massType

  \brief The mass type, monoisotopic or average to compute.

  \sa MassType
  */

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_capping

  \brief The  cap type, left or right to account for in the calculations.

  \sa CapType
  */

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_monomerEntities

  \brief The \l Monomer entities to account for in the calculations.

  \sa MonomerChemEnt
  */

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_polymerEntities

  \brief The \l Polymer entities to account for in the calculations.

  \sa PolymerChemEnt
  */

/*!
  \variable MsXpS::libXpertMass::CalcOptions::m_selectionType

  \brief The manner the monomers need to be accounted for: as residual chains
or as finished-polymerization state \l{Oligomer}s.

  The calculations might consider only the residual chain. In that case, only
the mass of the monomers is considered and then the polymer is not in its
finished polymerization state. If that latter state is required, then, the
residual chain must be capped with the left end cap and the right end cap.

\sa MsXpS::libXpertMass::SelectionType
  */

/*!
\brief Constructs a CalcOptions instance.
*/
CalcOptions::CalcOptions()
{
  m_deepCalculation = false;
  m_massType        = MassType::MASS_BOTH;
  m_capping         = CAP_BOTH;
  m_monomerEntities = MONOMER_CHEMENT_NONE;
  m_polymerEntities = POLYMER_CHEMENT_NONE;
}

/*!
\brief Constructs a CalcOptions instance.

All the members are initialized using the parameters:

\a deepCalculation: m_deepCalculation

\a massType: m_massType

\a capping: m_capping

\a monomerEntities: m_monomerEntities

\a polymerEntities: m_polymerEntities
*/
CalcOptions::CalcOptions(bool deepCalculation,
                         int massType,
                         int capping,
                         int monomerEntities,
                         int polymerEntities)
  : m_deepCalculation(deepCalculation),
    m_massType(massType),
    m_capping(capping),
    m_monomerEntities(monomerEntities),
    m_polymerEntities(polymerEntities)
{
}

/*!
\brief Construct a CalcOptions instance as a copy of \a other.
*/
CalcOptions::CalcOptions(const CalcOptions &other)
  : m_deepCalculation(other.m_deepCalculation),
    m_coordinateList(other.m_coordinateList),
    m_massType(other.m_massType),
    m_capping(other.m_capping),
    m_monomerEntities(other.m_monomerEntities),
    m_polymerEntities(other.m_polymerEntities),
    m_selectionType(other.m_selectionType)
{
}


/*!
  \brief Destructs this CalcOptions object.

  All the Coordinates in the member CoordinateList are deleted.
  */
CalcOptions::~CalcOptions()
{
  // Free all the coordinates from the list.
  while(!m_coordinateList.isEmpty())
    delete(m_coordinateList.takeFirst());
}


/*!
  \brief Assigns \a other to this CalcOptions instance.

  The copy is deep, with all the Coordinates in the \a{other}'s CoordinateList
being copied to this CalcOptions instance.

Returns a reference to this CalcOptions object.
*/

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

  m_deepCalculation = other.m_deepCalculation;
  m_massType        = other.m_massType;
  m_capping         = other.m_capping;
  m_monomerEntities = other.m_monomerEntities;
  m_polymerEntities = other.m_polymerEntities;

  m_coordinateList.empty();
  setCoordinateList(other.m_coordinateList);

  setSelectionType(other.m_selectionType);

  return *this;
}

/*!
\brief Sets to \a deep the configuration defining if the mass calculations must
involve the recalculation of the masses of all the monomers.

\sa m_deepCalculation
*/
void
CalcOptions::setDeepCalculation(bool deep)
{
  m_deepCalculation = deep;
}


//! Returns if the calculation is deep.
/*!
  \brief Returns if the calculation should be deep.

\sa m_deepCalculation
*/
bool
CalcOptions::isDeepCalculation() const
{
  return m_deepCalculation;
}

/*!
\brief Adds a copy of \a coordinates to the CoordinateList.

\note The CoordinateList' is first emptied,
essentially replacing its contents with a copy of \a coordinates.
*/
void
CalcOptions::setCoordinateList(const Coordinates &coordinates)
{
  m_coordinateList.setCoordinates(coordinates);
}

/*!
\brief Allocates a copy of each Coordinates instance in \a list and adds
it to the CoordinateList.

\note The CoordinateList is first emptied, essentially replacing its contents
with a copy of those in \a list.
*/
void
CalcOptions::setCoordinateList(const CoordinateList &list)
{
  m_coordinateList.setCoordinates(list);
}

/*!
\brief Returns the CoordinateList member.
*/
const CoordinateList &
CalcOptions::coordinateList() const
{
  return m_coordinateList;
}

/*!
\brief Sets the mass type to \a mass_type.

\sa m_massType
*/
void
CalcOptions::setMassType(int mass_type)
{
  m_massType = mass_type;
}


/*!
\brief Returns the mass type.

\sa m_massType
*/
int
CalcOptions::massType() const
{
  return m_massType;
}

/*!
\brief Set the selection type to \a type.

\sa m_selectionType
*/
void
CalcOptions::setSelectionType(SelectionType type)
{
  m_selectionType = type;
}

/*!
\brief Returns the selection type.

\sa m_selectionType
*/
SelectionType
CalcOptions::selectionType() const
{
  return m_selectionType;
}

/*!
\brief Set the cap type to \a cap_type.

\sa m_capping
*/
void
CalcOptions::setCapping(int cap_type)
{
  m_capping = cap_type;
}

/*!
\brief Returns the cap type .

\sa m_capping
*/
int
CalcOptions::capping() const
{
  return m_capping;
}

/*!
  \brief Sets the monomer entities to \a entities.

  \sa m_monomerEntities
*/
void
CalcOptions::setMonomerEntities(int entities)
{
  m_monomerEntities = entities;
}


/*!
  \brief Returns the monomer entities.

  \sa m_monomerEntities
*/
int
CalcOptions::monomerEntities() const
{
  return m_monomerEntities;
}


/*!
  \brief Sets the polymer entities to \a entities.

  \sa m_polymerEntities
*/
void
CalcOptions::setPolymerEntities(int entities)
{
  m_polymerEntities = entities;
}

/*!
  \brief Returns the polymer entities.

  \sa m_polymerEntities
*/
int
CalcOptions::polymerEntities() const
{
  return m_polymerEntities;
}

/*!
\brief Outputs a string describing this CalcOptions instance using qDebug().
*/
void
CalcOptions::debugPutStdErr() const
{
  qDebug() << "\n~~~~~~~~~~~~~~CalcOptions instance:\n"
           << this << "\n"
           << "m_deepCalculation:" << m_deepCalculation << "\n"
           << "m_coordinateList: \n";

  for(int iter = 0; iter < m_coordinateList.size(); ++iter)
    {
      Coordinates *coord = m_coordinateList.at(iter);
      qDebug() << "Iterated Coordinates at index" << iter << ":"
               << "[" << coord->start() << "-" << coord->end() << "]\n";
    }

  qDebug() << "m_capping:" << m_capping << "\n"
           << "m_monomerEntities:" << m_monomerEntities << "\n"
           << "m_polymerEntities:" << m_polymerEntities << "\n"
           << "m_selectionType:" << m_selectionType << "\n"
           << "~~~~~~~~~~~~~~\n";
}

} // namespace libXpertMass

} // namespace MsXpS
