/**
 * \file grouping/ptm/ptmislandsubgroup.cpp
 * \date 29/5/2017
 * \author Olivier Langella
 * \brief object to group ptm islands sharing the same set of sample scans with
 * different proteins
 */

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

#include "ptmislandsubgroup.h"
#include "ptmgroupingexperiment.h"

PtmIslandSubgroup::PtmIslandSubgroup(PtmIslandSp ptm_island_sp)
{
  _ptm_island_list.push_back(ptm_island_sp);
  _sample_scan_set = ptm_island_sp.get()->getSampleScanSet();
}

PtmIslandSubgroup::PtmIslandSubgroup(const PtmIslandSubgroup &other)
{
  _ptm_island_list = other._ptm_island_list;
  _sample_scan_set = other._sample_scan_set;
}

PtmIslandSubgroup::~PtmIslandSubgroup()
{
}
const PtmIsland *
PtmIslandSubgroup::getFirstPtmIsland() const
{
  return _ptm_island_list.begin()->get();
}

const PtmIslandGroup *
PtmIslandSubgroup::getPtmIslandGroup() const
{
  return _ptm_island_group_p;
}

unsigned int
PtmIslandSubgroup::getSubgroupNumber() const
{
  return _subgroup_number;
}
void
PtmIslandSubgroup::setSubgroupNumber(unsigned int number)
{
  _subgroup_number = number;

  for(PtmIslandSp ptm_island : _ptm_island_list)
    {
      ptm_island.get()->setPtmIslandSubgroup(this);
    }
  std::sort(
    _ptm_island_list.begin(),
    _ptm_island_list.end(),
    [](const PtmIslandSp &a, const PtmIslandSp &b) {
      return (
        a.get()->getProteinMatch()->getProteinXtpSp().get()->getAccession() <
        b.get()->getProteinMatch()->getProteinXtpSp().get()->getAccession());
    });

  unsigned int prot_number = 0;
  for(PtmIslandSp ptm_island : _ptm_island_list)
    {
      prot_number++;
      ptm_island.get()->setProteinNumber(prot_number);
    }
}
void
PtmIslandSubgroup::setPtmIslandGroup(PtmIslandGroup *p_ptm_island_group)
{
  _ptm_island_group_p = p_ptm_island_group;
  std::sort(
    _ptm_island_list.begin(),
    _ptm_island_list.end(),
    [](const PtmIslandSp &a, const PtmIslandSp &b) {
      return (
        a.get()->getProteinMatch()->getProteinXtpSp().get()->getAccession() <
        b.get()->getProteinMatch()->getProteinXtpSp().get()->getAccession());
    });
}
const std::vector<PtmIslandSp> &
PtmIslandSubgroup::getPtmIslandList() const
{
  return _ptm_island_list;
}
std::size_t
PtmIslandSubgroup::countSampleScan() const
{
  return _sample_scan_set.size();
}

std::size_t
PtmIslandSubgroup::countPtmInSample(
  const PtmGroupingExperiment *p_ptm_grouping_experiment,
  const MsRun *p_msrun_id,
  const Label *p_label) const
{
  std::set<std::size_t> count_sample_scan;
  for(auto ptm_island_sp : _ptm_island_list)
    {
      for(auto &peptide_match : ptm_island_sp.get()->getPeptideMatchList())
        {
          if(p_ptm_grouping_experiment->countPeptideMatchPtm(peptide_match) >=
             1)
            {
              if(p_label != nullptr)
                {
                  if(peptide_match.getPeptideEvidence()
                       ->getPeptideXtpSp()
                       .get()
                       ->getLabel() != p_label)
                    continue;
                }
              if(peptide_match.getPeptideEvidence()->getMsRunP() == p_msrun_id)
                count_sample_scan.insert(
                  peptide_match.getPeptideEvidence()->getHashSampleScan());
            }
        }
    }
  return count_sample_scan.size();
}


bool
PtmIslandSubgroup::containsProteinMatchFrom(
  PtmIslandSubgroup *ptm_island_subgroup_p)
{
  for(PtmIslandSp ptm_island_sp : _ptm_island_list)
    {
      if(std::any_of(ptm_island_subgroup_p->_ptm_island_list.begin(),
                     ptm_island_subgroup_p->_ptm_island_list.end(),
                     [ptm_island_sp](PtmIslandSp element) {
                       return (element.get()->getProteinMatch() ==
                               ptm_island_sp.get()->getProteinMatch());
                     }))
        {
          return true;
        }
    }
  return false;
}

bool
PtmIslandSubgroup::mergePtmIslandSp(PtmIslandSp ptm_island_sp)
{
  if(_sample_scan_set == ptm_island_sp.get()->getSampleScanSet())
    {
      // merge
      _ptm_island_list.push_back(ptm_island_sp);
      return true;
    }
  return false;
}
