
/*******************************************************************************
 * 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 <QDebug>
#include "grppeptideset.h"

using namespace pappso;
GrpPeptideSet::GrpPeptideSet()
{
}
GrpPeptideSet::GrpPeptideSet(const GrpProtein *p_protein)
{
  auto it = p_protein->begin();
  while(it != p_protein->end())
    {
      m_peptidePtrList.push_back(*it);
      it++;
    }
}
GrpPeptideSet::GrpPeptideSet(const GrpPeptideSet &other) : m_peptidePtrList(other.m_peptidePtrList)
{
}

GrpPeptideSet::~GrpPeptideSet()
{
}

GrpPeptideSet &
GrpPeptideSet::operator=(const GrpPeptideSet &other)
{
  m_peptidePtrList = other.m_peptidePtrList;
  return *this;
}

bool
GrpPeptideSet::operator==(const GrpPeptideSet &other) const
{
  if(m_peptidePtrList.size() != other.m_peptidePtrList.size())
    {
      return false;
    }
  return privContainsAll(other);
}

bool
GrpPeptideSet::contains(const GrpPeptide *p_grp_peptide) const
{
  if(std::find(m_peptidePtrList.begin(), m_peptidePtrList.end(), p_grp_peptide) ==
     m_peptidePtrList.end())
    {
      return false;
    }
  return true;
}

bool
GrpPeptideSet::containsAll(const GrpPeptideSet &peptideSetIn) const
{
  if(m_peptidePtrList.size() < peptideSetIn.m_peptidePtrList.size())
    {
      return false;
    }
  return privContainsAll(peptideSetIn);
}

bool
GrpPeptideSet::biggerAndContainsAll(const GrpPeptideSet &peptideSetIn) const
{
  if(m_peptidePtrList.size() > peptideSetIn.m_peptidePtrList.size())
    {
      return privContainsAll(peptideSetIn);
    }
  return false;
}

bool
GrpPeptideSet::privContainsAll(const GrpPeptideSet &peptideSetIn) const
{
  std::list<GrpPeptide *>::const_iterator innerIt, outerIt, innerEnd, outerEnd;
  innerIt  = peptideSetIn.m_peptidePtrList.begin();
  innerEnd = peptideSetIn.m_peptidePtrList.end();
  outerIt  = m_peptidePtrList.begin();
  outerEnd = m_peptidePtrList.end();


  while((innerIt != innerEnd) && (outerIt != outerEnd))
    {
      if(*innerIt > *outerIt)
        {
          outerIt++;
          continue;
        }
      if(*innerIt < *outerIt)
        {
          return false;
        }
      if(*innerIt == *outerIt)
        {
          innerIt++;
          outerIt++;
        }
    }
  if(innerIt == innerEnd)
    {
      return true;
    }
  return false;
}

bool
GrpPeptideSet::containsAny(const GrpPeptideSet &peptideSetIn) const
{
  std::list<GrpPeptide *>::const_iterator innerIt, outerIt, innerEnd, outerEnd;

  innerIt  = peptideSetIn.m_peptidePtrList.begin();
  innerEnd = peptideSetIn.m_peptidePtrList.end();
  outerIt  = m_peptidePtrList.begin();
  outerEnd = m_peptidePtrList.end();


  while((innerIt != innerEnd) && (outerIt != outerEnd))
    {
      if(*innerIt > *outerIt)
        {
          outerIt++;
          continue;
        }
      if(*innerIt < *outerIt)
        {
          innerIt++;
          continue;
        }
      if(*innerIt == *outerIt)
        {
          return true;
        }
    }
  return false;
}

void
GrpPeptideSet::addAll(const GrpPeptideSet &peptideSetIn)
{

  qDebug() << "GrpPeptideSet::addAll begin";
  std::list<GrpPeptide *>::iterator it(m_peptidePtrList.begin());
  std::list<GrpPeptide *>::iterator itEnd(m_peptidePtrList.end());
  std::list<GrpPeptide *>::const_iterator itIn(peptideSetIn.m_peptidePtrList.begin());
  std::list<GrpPeptide *>::const_iterator itInEnd(peptideSetIn.m_peptidePtrList.end());

  while((itIn != itInEnd) && (it != itEnd))
    {
      if(*itIn > *it)
        {
          it++;
          continue;
        }
      if(*itIn < *it)
        {
          it = m_peptidePtrList.insert(it, *itIn);
          it++;
          itIn++;
          continue;
        }
      if(*itIn == *it)
        {
          itIn++;
          it++;
        }
    }
  while(itIn != itInEnd)
    {
      m_peptidePtrList.push_back(*itIn);
      itIn++;
    }
  qDebug() << "GrpPeptideSet::addAll end";
}


void
GrpPeptideSet::numbering()
{
  qDebug() << "GrpPeptideSet::numbering begin";

  m_peptidePtrList.sort(
    [](GrpPeptide *first, GrpPeptide *second) { return ((*first) < (*second)); });
  unsigned int i = 1;
  for(auto &&p_grp_peptide : m_peptidePtrList)
    {
      p_grp_peptide->setRank(i);
      i++;
    }

  qDebug() << "GrpPeptideSet::numbering end";
}


void
GrpPeptideSet::setGroupNumber(unsigned int i)
{
  qDebug() << "GrpPeptideSet::setGroupNumber begin";
  for(auto &&p_grp_peptide : m_peptidePtrList)
    {
      p_grp_peptide->setGroupNumber(i);
    }

  qDebug() << "GrpPeptideSet::setGroupNumber end";
}

std::vector<const GrpPeptide *>
GrpPeptideSet::getGrpPeptideList() const
{
  std::vector<const GrpPeptide *> peptide_list;
  for(GrpPeptide *peptide : m_peptidePtrList)
    {
      peptide_list.push_back(peptide);
    }
  return peptide_list;
}

const QString
GrpPeptideSet::printInfos() const
{
  QString infos;
  std::list<GrpPeptide *>::const_iterator it(m_peptidePtrList.begin()),
    itEnd(m_peptidePtrList.end());


  while(it != itEnd)
    {
      infos.append((*it)->getSequence() + " " +
                   QString("0x%1").arg((quintptr)*it, QT_POINTER_SIZE * 2, 16, QChar('0')) + "\n");
      it++;
    }

  return infos;
}
