/* 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 <massxpert/nongui/OligomerList.hpp>
#include <massxpert/nongui/Polymer.hpp>

namespace msXpSmassXpert
{

OligomerList::OligomerList(QString name,
                           Polymer *polymer,
                           msXpS::MassType massType)
  : m_name(name), mp_polymer(polymer), m_massType(massType)
{
}


OligomerList::OligomerList(const OligomerList *other)
  : QList<Oligomer *>(*other),
    m_name(other->m_name),
    m_comment(other->m_comment),
    mp_polymer(other->mp_polymer),
    m_massType(other->m_massType)
{
  // And now copy all the items from other in here:
  for(int iter = 0; iter < other->size(); ++iter)
    append(new Oligomer(*other->at(iter)));
}


OligomerList::~OligomerList()
{
  //   qDebug() << __FILE__ << __LINE__
  // 	    << "Deleting all the oligomers in the list";
  qDeleteAll(begin(), end());
  clear();
}


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


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


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


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


const Polymer *
OligomerList::polymer() const
{
  return mp_polymer;
}


void
OligomerList::setMassType(msXpS::MassType massType)
{
  m_massType = massType;
}


const msXpS::MassType
OligomerList::massType() const
{
  return m_massType;
}


Oligomer *
OligomerList::findOligomerEncompassing(int index, int *listIndex)
{
  // Is there any oligomer that emcompasses the index ? If so return
  // its pointer. Start searching in the list at index *listIndex if
  // parameter non-0.

  int iter = 0;

  if(listIndex)
    {
      if(*listIndex >= size())
        return 0;

      if(*listIndex < 0)
        return 0;

      iter = *listIndex;
    }

  for(; iter < size(); ++iter)
    {
      Oligomer *oligomer = at(iter);

      if(oligomer->encompasses(index))
        {
          if(listIndex)
            *listIndex = iter;

          return oligomer;
        }
    }

  return 0;
}


Oligomer *
OligomerList::findOligomerEncompassing(const Monomer *monomer, int *listIndex)
{
  // Is there any oligomer that emcompasses the monomer ? If so return
  // its pointer. Start searching in the list at index *listIndex if
  // parameter non-0.

  Q_ASSERT(monomer);

  int iter = 0;

  if(listIndex)
    {
      if(*listIndex >= size())
        return 0;

      if(*listIndex < 0)
        return 0;

      iter = *listIndex;
    }

  for(; iter < size(); ++iter)
    {
      Oligomer *oligomer = at(iter);

      if(oligomer->encompasses(monomer))
        {
          if(listIndex)
            *listIndex = iter;

          return oligomer;
        }
    }

  return 0;
}


QString *
OligomerList::makeMassText(msXpS::MassType massType)
{
  QString *text = new QString();

  msXpS::MassType localMassType = msXpS::MassType::MASS_NONE;

  if(massType == msXpS::MassType::MASS_BOTH)
    {
      delete text;
      return 0;
    }

  if(massType & msXpS::MassType::MASS_NONE)
    localMassType = m_massType;
  else
    localMassType = massType;

  for(int iter = 0; iter < size(); ++iter)
    {
      double value = 0;

      if(localMassType & msXpS::MassType::MASS_MONO)
        value = at(iter)->mono();
      else
        value = at(iter)->avg();

      QString mass;
      mass.setNum(value, 'f', msXpS::OLIGOMER_DEC_PLACES);

      text->append(mass + "\n");
    }

  return text;
}


bool
OligomerList::lessThanMono(const Oligomer *o1, const Oligomer *o2)
{
  qDebug() << "o1 is:" << o1 << "o2 is:" << o2;

  return true;
}


bool
OligomerList::lessThanAvg(const Oligomer *o1, const Oligomer *o2)
{
  qDebug() << "o1 is:" << o1 << "o2 is:" << o2;

  return true;
}


void
OligomerList::sortAscending()
{
  // We only can sort if this instance knows which mass type it should
  // handle, and that cannot be anything other than msXpS::MassType::MASS_MONO
  // or MASS_AVG.

  if(m_massType == msXpS::MassType::MASS_BOTH ||
     m_massType & msXpS::MassType::MASS_NONE)
    {
      qDebug() << "Could not sort the oligomer list: "
                  "m_massType is not correct";

      return;
    }

  if(m_massType == msXpS::MassType::MASS_MONO)
    qSort(begin(), end(), OligomerList::lessThanMono);
  else
    qSort(begin(), end(), OligomerList::lessThanAvg);
}

} // namespace msXpSmassXpert
