
/*******************************************************************************
 * Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>.
 *
 * This file is part of XTPcpp.
 *
 *     XTPcpp 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.
 *
 *     XTPcpp 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 XTPcpp.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <olivier.langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include "groupinggroup.h"
#include <core/proteinmatch.h>
#include <core/peptidematch.h>
#include <pappsomspp/grouping/grppeptide.h>
#include <pappsomspp/utils.h>
#include <set>

GroupingGroup::GroupingGroup()
{
}

GroupingGroup::~GroupingGroup()
{
}

const std::vector<std::pair<unsigned int, const PeptideEvidence *>> &
GroupingGroup::getPairSgNumberPeptideEvidenceList() const
{
  return _pair_sg_number_peptide_evidence_list;
}
unsigned int
GroupingGroup::getGroupNumber() const
{
  return _group_number;
}
unsigned int
GroupingGroup::getNumberOfSubgroups() const
{
  return _number_of_subgroup;
}
const std::vector<const ProteinMatch *> &
GroupingGroup::getProteinMatchList() const
{
  return _protein_match_list;
}
std::vector<const PeptideEvidence *>
GroupingGroup::getPeptideEvidenceList() const
{
  std::vector<const PeptideEvidence *> peptide_match_list;
  for(auto &&pair_peptide_match : _pair_sg_number_peptide_evidence_list)
    {
      peptide_match_list.push_back(pair_peptide_match.second);
    }
  return peptide_match_list;
}

const QStringList
GroupingGroup::getSubgroupIdList(const PeptideEvidence *p_peptide_match) const
{
  std::set<unsigned int> subgroup_list;
  pappso::GrpPeptide *p_grp_peptide = p_peptide_match->getGrpPeptideSp().get();
  if(p_grp_peptide != nullptr)
    {
      for(auto &&pair_peptide_match : _pair_sg_number_peptide_evidence_list)
        {
          if(pair_peptide_match.second->getGrpPeptideSp().get() ==
             p_grp_peptide)
            {
              subgroup_list.insert(pair_peptide_match.first);
            }
        }
    }


  QStringList sg_str_list;
  for(unsigned int sgnum : subgroup_list)
    {
      sg_str_list << QString("%1.%2")
                       .arg(
                         pappso::Utils::getLexicalOrderedString(_group_number))
                       .arg(pappso::Utils::getLexicalOrderedString(sgnum));
    }
  return sg_str_list;
}

unsigned int
GroupingGroup::countSubgroupPresence(
  const PeptideEvidence *p_peptide_evidence) const
{
  std::set<unsigned int> subgroup_list;
  pappso::GrpPeptide *p_grp_peptide =
    p_peptide_evidence->getGrpPeptideSp().get();
  if(p_grp_peptide != nullptr)
    {
      for(auto &&pair_peptide_match : _pair_sg_number_peptide_evidence_list)
        {
          if(pair_peptide_match.second->getGrpPeptideSp().get() ==
             p_grp_peptide)
            {
              subgroup_list.insert(pair_peptide_match.first);
            }
        }
    }
  return subgroup_list.size();
}

std::size_t
GroupingGroup::countSpecificSampleScan(const ProteinMatch *p_protein_match,
                                       ValidationState state,
                                       const MsRun *p_msrun_id,
                                       const Label *p_label) const
{
  if(_number_of_subgroup == 1)
    {
      return p_protein_match->countSampleScan(state, p_msrun_id);
    }
  std::set<size_t> spectrum_list_in;
  for(auto &&p_peptide_match : p_protein_match->getPeptideMatchList())
    {
      if(p_peptide_match.getPeptideEvidence()->getValidationState() >= state)
        {
          if(p_msrun_id == nullptr)
            {
              spectrum_list_in.insert(
                p_peptide_match.getPeptideEvidence()->getHashSampleScan());
            }
          else
            {
              if(p_label != nullptr)
                {
                  if((p_peptide_match.getPeptideEvidence()->getMsRunP() ==
                      p_msrun_id) &&
                     (p_peptide_match.getPeptideEvidence()
                        ->getPeptideXtpSp()
                        .get()
                        ->getLabel() == p_label))
                    {
                      spectrum_list_in.insert(
                        p_peptide_match.getPeptideEvidence()
                          ->getHashSampleScan());
                    }
                }
              else
                {
                  if(p_peptide_match.getPeptideEvidence()->getMsRunP() ==
                     p_msrun_id)
                    {
                      spectrum_list_in.insert(
                        p_peptide_match.getPeptideEvidence()
                          ->getHashSampleScan());
                    }
                }
            }
        }
    }
  std::set<size_t> spectrum_list_out;
  unsigned int sg_number =
    p_protein_match->getGrpProteinSp().get()->getSubGroupNumber();
  for(auto &&pair_peptide_match : _pair_sg_number_peptide_evidence_list)
    {
      if(pair_peptide_match.first != sg_number)
        {
          spectrum_list_out.insert(
            pair_peptide_match.second->getHashSampleScan());
        }
    }

  std::size_t count = 0;
  for(size_t sample_scan : spectrum_list_in)
    {
      std::set<size_t>::const_iterator it = spectrum_list_out.find(sample_scan);
      if(it == spectrum_list_out.end())
        {
          count++;
        }
    }
  return count;
}

std::size_t
GroupingGroup::countSpecificSequenceLi(const ProteinMatch *p_protein_match,
                                       ValidationState state,
                                       const MsRun *p_msrun_id,
                                       const Label *p_label) const
{
  if(_number_of_subgroup == 1)
    {
      return p_protein_match->countSequenceLi(state, p_msrun_id, p_label);
    }
  std::set<QString> sequence_list_in;
  for(auto &&p_peptide_match : p_protein_match->getPeptideMatchList())
    {
      if(p_peptide_match.getPeptideEvidence()->getValidationState() >= state)
        {
          if(p_msrun_id == nullptr)
            {
              sequence_list_in.insert(p_peptide_match.getPeptideEvidence()
                                        ->getPeptideXtpSp()
                                        .get()
                                        ->getSequenceLi());
            }
          else
            {
              if(p_label != nullptr)
                {
                  if((p_peptide_match.getPeptideEvidence()->getMsRunP() ==
                      p_msrun_id) &&
                     (p_peptide_match.getPeptideEvidence()
                        ->getPeptideXtpSp()
                        .get()
                        ->getLabel() == p_label))
                    {
                      sequence_list_in.insert(
                        p_peptide_match.getPeptideEvidence()
                          ->getPeptideXtpSp()
                          .get()
                          ->getSequenceLi());
                    }
                }
              else
                {
                  if(p_peptide_match.getPeptideEvidence()->getMsRunP() ==
                     p_msrun_id)
                    {
                      sequence_list_in.insert(
                        p_peptide_match.getPeptideEvidence()
                          ->getPeptideXtpSp()
                          .get()
                          ->getSequenceLi());
                    }
                }
            }
        }
    }
  std::set<QString> sequence_list_out;
  unsigned int sg_number =
    p_protein_match->getGrpProteinSp().get()->getSubGroupNumber();
  for(auto &&pair_peptide_match : _pair_sg_number_peptide_evidence_list)
    {
      if(pair_peptide_match.first != sg_number)
        {
          sequence_list_out.insert(pair_peptide_match.second->getPeptideXtpSp()
                                     .get()
                                     ->getSequenceLi());
        }
    }

  std::size_t count = 0;
  for(const QString &sequence : sequence_list_in)
    {
      std::set<QString>::const_iterator it = sequence_list_out.find(sequence);
      if(it == sequence_list_out.end())
        {
          count++;
        }
    }
  return count;
}

unsigned int
GroupingGroup::countProteinInSubgroup(unsigned int subgroup_number) const
{
  return std::count_if(
    _protein_match_list.begin(),
    _protein_match_list.end(),
    [subgroup_number](const ProteinMatch *p_protein_match) {
      if(p_protein_match->getGrpProteinSp().get()->getSubGroupNumber() ==
         subgroup_number)
        {
          return true;
        }
      else
        {
          return false;
        }
    });
}

QString
GroupingGroup::getProteinGroupingIdOfSubgroup(
  unsigned int subgroup_number) const
{
  return QString("%1.%2.a1")
    .arg(pappso::Utils::getLexicalOrderedString(_group_number))
    .arg(pappso::Utils::getLexicalOrderedString(subgroup_number));
}

void
GroupingGroup::add(const ProteinMatch *p_protein_match)
{
  _group_number = p_protein_match->getGrpProteinSp().get()->getGroupNumber();
  _protein_match_list.push_back(p_protein_match);
  if(p_protein_match->getGrpProteinSp().get()->getRank() == 1)
    {
      _number_of_subgroup++;
      unsigned int sg_number =
        p_protein_match->getGrpProteinSp().get()->getSubGroupNumber();

      for(auto &&peptide_match : p_protein_match->getPeptideMatchList())
        {
          if(peptide_match.getPeptideEvidence()->isValidAndChecked())
            {
              _pair_sg_number_peptide_evidence_list.push_back(
                std::pair<unsigned int, const PeptideEvidence *>(
                  sg_number, peptide_match.getPeptideEvidence()));
            }
        }
    }
}
