/**
 * \file grouping/ptm/ptmislandgroup.cpp
 * \date 29/5/2017
 * \author Olivier Langella
 * \brief object to group subgroups of ptmislands sharing at least one protein
 */

/*******************************************************************************
 * 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 "ptmislandgroup.h"

PtmIslandGroup::PtmIslandGroup(PtmIslandSubgroupSp ptm_island_subgroup_sp)
{
  _ptm_island_subgroup_list.push_back(ptm_island_subgroup_sp);
}

PtmIslandGroup::PtmIslandGroup(const PtmIslandGroup &other)
{
  _ptm_island_subgroup_list = other._ptm_island_subgroup_list;
}

PtmIslandGroup::~PtmIslandGroup()
{
}

QString
PtmIslandGroup::getFirstAccession() const
{
  if(_ptm_island_subgroup_list.size() == 0)
    return QString();
  QStringList accession_list;
  for(PtmIslandSubgroupSp ptm_island_subgroup : _ptm_island_subgroup_list)
    {
      for(PtmIslandSp ptm_island :
          ptm_island_subgroup.get()->getPtmIslandList())
        {
          accession_list << ptm_island.get()
                              ->getProteinMatch()
                              ->getProteinXtpSp()
                              .get()
                              ->getAccession();
        }
    }
  accession_list.sort();

  return accession_list[0];
}

unsigned int
PtmIslandGroup::getGroupNumber() const
{
  return _group_number;
}
void
PtmIslandGroup::setGroupNumber(unsigned int number)
{
  _group_number = number;
  for(PtmIslandSubgroupSp ptm_island_subgroup : _ptm_island_subgroup_list)
    {
      ptm_island_subgroup.get()->setPtmIslandGroup(this);
    }
  std::sort(_ptm_island_subgroup_list.begin(),
            _ptm_island_subgroup_list.end(),
            [](const PtmIslandSubgroupSp &a, const PtmIslandSubgroupSp &b) {
              return (a.get()->getFirstPtmIsland()->getProteinStartPosition() <
                      b.get()->getFirstPtmIsland()->getProteinStartPosition());
            });

  unsigned int sg_number = 0;
  for(PtmIslandSubgroupSp ptm_island_subgroup : _ptm_island_subgroup_list)
    {
      sg_number++;
      ptm_island_subgroup.get()->setSubgroupNumber(sg_number);
    }
}
bool
PtmIslandGroup::operator<(const PtmIslandGroup &other) const
{
  // if (_ptm_island_subgroup_list.size() ==
  // other._ptm_island_subgroup_list.size()) {
  if(maxCountSampleScan() == other.maxCountSampleScan())
    {
      return (getFirstAccession() < other.getFirstAccession());
    }
  else
    {
      return (maxCountSampleScan() > other.maxCountSampleScan());
    }
  //}
  // else {
  //    return (_ptm_island_subgroup_list.size() <
  //    other._ptm_island_subgroup_list.size());
  //}
}
unsigned int
PtmIslandGroup::maxCountSampleScan() const
{
  std::vector<PtmIslandSubgroupSp>::const_iterator it_result = std::max_element(
    _ptm_island_subgroup_list.begin(),
    _ptm_island_subgroup_list.end(),
    [](const PtmIslandSubgroupSp &a, const PtmIslandSubgroupSp &b) {
      return (a.get()->countSampleScan() < b.get()->countSampleScan());
    });
  return it_result->get()->countSampleScan();
}

bool
PtmIslandGroup::mergePtmIslandSubgroupSp(
  PtmIslandSubgroupSp ptm_island_subgroup_sp)
{

  // http://en.cppreference.com/w/cpp/algorithm/all_any_none_of
  if(std::any_of(_ptm_island_subgroup_list.begin(),
                 _ptm_island_subgroup_list.end(),
                 [ptm_island_subgroup_sp](PtmIslandSubgroupSp element) {
                   return element.get()->containsProteinMatchFrom(
                     ptm_island_subgroup_sp.get());
                 }))
    {
      // accept this subgroup
      _ptm_island_subgroup_list.push_back(ptm_island_subgroup_sp);
      return true;
    }
  return false;
}
