
/*******************************************************************************
 * 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 <QObject>

#include "grpmappeptidetosubgroupset.h"
#include "grppeptideset.h"

#include "pappsomspp/core/pappsoexception.h"


namespace pappso
{
GrpMapPeptideToSubGroupSet::GrpMapPeptideToSubGroupSet()
{
}

GrpMapPeptideToSubGroupSet::~GrpMapPeptideToSubGroupSet()
{
}

GrpMapPeptideToSubGroupSet::GrpMapPeptideToSubGroupSet(const GrpMapPeptideToSubGroupSet &other)
  : m_mapPeptideToSubGroupSet(other.m_mapPeptideToSubGroupSet)
{
}
unsigned int
GrpMapPeptideToSubGroupSet::GrpMapPeptideToSubGroupSet::size() const
{
  return m_mapPeptideToSubGroupSet.size();
}

void
GrpMapPeptideToSubGroupSet::getSubGroupSet(const GrpPeptideSet &peptide_set_in,
                                           GrpSubGroupSet &impacted_subgroup_set) const
{
  qDebug() << "GrpMapPeptideToSubGroupSet::getSubGroupSet begin ";
  auto it_peptide_end = peptide_set_in.m_peptidePtrList.end();
  std::map<GrpPeptide *, GrpSubGroupSet>::const_iterator it_map_end =
    m_mapPeptideToSubGroupSet.end();

  for(auto it_peptide = peptide_set_in.m_peptidePtrList.begin(); it_peptide != it_peptide_end;
      it_peptide++)
    {
      std::map<GrpPeptide *, GrpSubGroupSet>::const_iterator it_map =
        m_mapPeptideToSubGroupSet.find(*it_peptide);
      if(it_map != it_map_end)
        {
          impacted_subgroup_set.addAll(it_map->second);
        }
    }
  qDebug() << "GrpMapPeptideToSubGroupSet::getSubGroupSet end ";
}
void
GrpMapPeptideToSubGroupSet::check(std::list<GrpSubGroupSp> &m_grpSubGroupSpList) const
{
  qDebug() << "GrpMapPeptideToSubGroupSet::std begin ";
  GrpMapPeptideToSubGroupSet test(*this);
  qDebug() << "GrpMapPeptideToSubGroupSet::std before test.size() " << test.size();

  for(auto pair : m_mapPeptideToSubGroupSet)
    {
      qDebug() << "GrpMapPeptideToSubGroupSet::std before peptide " << pair.first->getSequence()
               << " " << pair.first;
    }

  for(GrpSubGroupSp &sub_group_sp : m_grpSubGroupSpList)
    {
      test.remove(sub_group_sp.get());
    }
  qDebug() << "GrpMapPeptideToSubGroupSet::std after test.size() " << test.size();

  qDebug() << "GrpMapPeptideToSubGroupSet::std begin ";
}

void
GrpMapPeptideToSubGroupSet::remove(GrpSubGroup *p_remove_sub_group)
{
  qDebug() << "GrpMapPeptideToSubGroupSet::remove begin "
           << p_remove_sub_group->getFirstAccession();
  // std::list<std::pair<GrpPeptide*, GrpSubGroupSet>>
  // m_mapPeptideToSubGroupSet;
  const GrpPeptideSet &peptide_set_in = p_remove_sub_group->getPeptideSet();

  auto it_peptide_end = peptide_set_in.m_peptidePtrList.end();
  std::map<GrpPeptide *, GrpSubGroupSet>::const_iterator it_map_end =
    m_mapPeptideToSubGroupSet.end();

  for(auto it_peptide = peptide_set_in.m_peptidePtrList.begin(); it_peptide != it_peptide_end;
      it_peptide++)
    {
      std::map<GrpPeptide *, GrpSubGroupSet>::iterator it_map =
        m_mapPeptideToSubGroupSet.find(*it_peptide);
      if(it_map != it_map_end)
        {
          it_map->second.remove(p_remove_sub_group);
          if(it_map->second.size() == 0)
            {
              m_mapPeptideToSubGroupSet.erase(it_map);
            }
        }
      else
        {
          throw PappsoException(QObject::tr("remove ERROR, peptide %1 from subgroup %2 not "
                                            "referenced in GrpMapPeptideToSubGroupSet")
                                  .arg((*it_peptide)->getSequence())
                                  .arg(p_remove_sub_group->getFirstAccession()));
        }
    }

  qDebug() << "GrpMapPeptideToSubGroupSet::remove end " << p_remove_sub_group->getFirstAccession();
}
void
GrpMapPeptideToSubGroupSet::add(GrpSubGroup *p_add_sub_group)
{
  qDebug() << "GrpMapPeptideToSubGroupSet::add begin  m_mapPeptideToSubGroupSet.size()"
           << m_mapPeptideToSubGroupSet.size();


  const GrpPeptideSet &peptide_set_in = p_add_sub_group->getPeptideSet();

  auto it_peptide_end = peptide_set_in.m_peptidePtrList.end();

  for(auto it_peptide = peptide_set_in.m_peptidePtrList.begin(); it_peptide != it_peptide_end;
      it_peptide++)
    {
      std::pair<std::map<GrpPeptide *, GrpSubGroupSet>::iterator, bool> ret =
        m_mapPeptideToSubGroupSet.insert(
          std::pair<GrpPeptide *, GrpSubGroupSet>(*it_peptide, GrpSubGroupSet()));
      // if (ret.second==false) { => key already exists
      ret.first->second.add(p_add_sub_group);
    }

  qDebug() << "GrpMapPeptideToSubGroupSet::add end";
}


bool
GrpMapPeptideToSubGroupSet::hasSpecificPeptide(const GrpSubGroup *p_sub_group) const
{
  qDebug() << "GrpMapPeptideToSubGroupSet::hasSpecificPeptide begin";

  const GrpPeptideSet &peptide_set_in = p_sub_group->getPeptideSet();

  auto it_peptide_end = peptide_set_in.m_peptidePtrList.end();
  std::map<GrpPeptide *, GrpSubGroupSet>::const_iterator it_map_end =
    m_mapPeptideToSubGroupSet.end();

  for(auto it_peptide = peptide_set_in.m_peptidePtrList.begin(); it_peptide != it_peptide_end;
      it_peptide++)
    {
      std::map<GrpPeptide *, GrpSubGroupSet>::const_iterator it_map =
        m_mapPeptideToSubGroupSet.find(*it_peptide);
      if(it_map != it_map_end)
        {
          if(it_map->second.size() == 1)
            {
              return true;
            }
        }
      else
        {
          throw PappsoException(QObject::tr("hasSpecificPeptide ERROR, peptide %1 from subgroup %2 "
                                            "not referenced in GrpMapPeptideToSubGroupSet")
                                  .arg((*it_peptide)->getSequence())
                                  .arg(p_sub_group->getFirstAccession()));
        }
    }

  qDebug() << "GrpMapPeptideToSubGroupSet::hasSpecificPeptide end";
  return false;
}

const QString
GrpMapPeptideToSubGroupSet::printInfos() const
{
  QString infos;
  auto itMap    = m_mapPeptideToSubGroupSet.begin();
  auto itMapEnd = m_mapPeptideToSubGroupSet.end();

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

  return infos;
}

} // namespace pappso
