/**
 * \file pappsomspp/processing/filters/filterexclusionmz.cpp
 * \date 09/02/2021
 * \author Thomas Renne
 * \brief Delete small peaks in the exclusion range
 */

/*******************************************************************************
 * Copyright (c) 2021 Thomas Renne <thomas.renne@e.email>.
 *
 * 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/>.
 *
 ******************************************************************************/

#include "filterexclusionmz.h"
#include <QDebug>
#include "../../exception/exceptionnotrecognized.h"

using namespace pappso;

FilterMzExclusion::FilterMzExclusion(const QString &strBuildParams)
{
  buildFilterFromString(strBuildParams);
}

FilterMzExclusion::FilterMzExclusion(pappso::PrecisionPtr precision_ptr)
  : m_exclusionPrecision(precision_ptr)
{
}

FilterMzExclusion::FilterMzExclusion(const pappso::FilterMzExclusion &other)
  : m_exclusionPrecision(other.m_exclusionPrecision)
{
}

FilterMzExclusion::~FilterMzExclusion()
{
}

void
pappso::FilterMzExclusion::buildFilterFromString(const QString &strBuildParams)
{
  qDebug();
  if(strBuildParams.startsWith("mzExclusion|"))
    {
      QStringList params =
        strBuildParams.split("|").back().split(";", Qt::SkipEmptyParts);

      QString precision = params.at(0);
      m_exclusionPrecision =
        PrecisionFactory::fromString(precision.replace("dalton", " dalton")
                                       .replace("ppm", " ppm")
                                       .replace("res", " res"));
    }
  else
    {
      throw pappso::ExceptionNotRecognized(
        QString("building mzExclusion from string %1 is not possible")
          .arg(strBuildParams));
    }
  qDebug();
}

pappso::Trace &
pappso::FilterMzExclusion::filter(pappso::Trace &data_points) const
{
  qDebug();
  qDebug() << "before" << data_points.size();
  data_points.sortY(SortOrder::descending);

  Trace new_trace = removeTraceInExclusionMargin(data_points);
  new_trace.sortX();
  data_points = std::move(new_trace);
  qDebug() << "after" << data_points.size();
  qDebug();
  return data_points;
}

QString
pappso::FilterMzExclusion::name() const
{
  return "mzExclusion";
}


QString
pappso::FilterMzExclusion::toString() const
{
  QString strCode =
    QString("%1|%2").arg(name()).arg(m_exclusionPrecision->toString());

  strCode.replace(" ", "");

  return strCode;
}

pappso::Trace
pappso::FilterMzExclusion::removeTraceInExclusionMargin(
  pappso::Trace &points) const
{
  Trace new_trace;
  std::vector<MzRange> excluded_ranges;

  for(auto &data_point : points)
    {
      auto exclude_index = excluded_ranges.begin(), end = excluded_ranges.end();

      exclude_index =
        std::find_if(exclude_index, end, [&data_point](MzRange range) {
          return (data_point.x >= range.lower() &&
                  data_point.x <= range.upper());
        });
      if(exclude_index == end)
        {
          new_trace.push_back(data_point);
          MzRange new_range(data_point.x, m_exclusionPrecision);
          excluded_ranges.push_back(new_range);
        }
    }

  return new_trace;
}
