/***************************************************************************
**
**  This file is part of QGpCoreStat.
**
**  QGpCoreStat 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.
**
**  QGpCoreStat 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2018-02-22
**  Copyright: 2018-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "SampleFilter.h"

/*!
  \class SampleFilter SampleFilter.h
  \brief Brief description of class still missing

  Full description of class still missing
*/

/*!
  Read and parse next available not blank and not starting with '#',
  and containing \a pattern.
*/
bool SampleFilter::Sample::read(const QString& line, int xColumn, int yColumn,
                               int noiseColumn, int powerColumn, int validColumn)
{
  TRACE;
  bool ok=true;
  LineParser lp(line);
  _time=lp.toDouble(0, ok);
  _frequency=lp.toDouble(1, ok);
  setX(lp.toDouble(xColumn, ok));
  setY(lp.toDouble(yColumn, ok));
  _noise=lp.toDouble(noiseColumn, ok);
  _power=lp.toDouble(powerColumn, ok);
  if(validColumn>=0) {
    setValid(lp.toInt(validColumn, ok)==1);
  } else {
    setValid(true);
  }
  setLine(line);
  if(ok) {
    return true;
  } else {
    App::log(tr("Error parsing line '%1'\n").arg(line) );
    return false;
  }
}

/*!
  Description of constructor still missing
*/
SampleFilter::SampleFilter()
{
  TRACE;
}

/*!
  Description of destructor still missing
*/
SampleFilter::~SampleFilter()
{
  TRACE;
}

void SampleFilter::filterPower(double relThreshold)
{
  TRACE;
  if(_samples.isEmpty()) {
    return;
  }
  std::sort(_samples.begin(), _samples.end(), lessThan);
  int n=_samples.count();
  double time0=_samples.first().time();
  double frequency0=_samples.first().frequency();
  double maxPower=0.0;
  int firstSampleIndex=0;
  for(int i=0; i<n; i++) {
    const Sample& s=_samples.at(i);
    if(s.time()==time0 && s.frequency()==frequency0) {
      if(s.power()>maxPower) {
        maxPower=s.power();
      }
    } else {
      selectPower(firstSampleIndex, i, maxPower*relThreshold);
      maxPower=s.power();
      firstSampleIndex=i;
      time0=s.time();
      frequency0=s.frequency();
    }
  }
  selectPower(firstSampleIndex, n, maxPower*relThreshold);
}

void SampleFilter::selectPower(int beginIndex, int endIndex, double minPower)
{
  for(int i=beginIndex; i<endIndex; i++) {
    Sample& s=_samples[i];
    if(s.power()<minPower) {
      s.setValid(false);
    }
  }
}

void SampleFilter::filterNoise(double threshold)
{
  TRACE;
  int n=_samples.count();
  for(int i=0; i<n; i++) {
    Sample& s=_samples[i];
    if(s.noise()>threshold) {
      s.setValid(false);
    }
  }
}

void SampleFilter::filterXMinimum(double threshold)
{
  TRACE;
  int n=_samples.count();
  for(int i=0; i<n; i++) {
    Sample& s=_samples[i];
    if(s.x()<threshold) {
      s.setValid(false);
    }
  }
}

void SampleFilter::filterXMaximum(double threshold)
{
  TRACE;
  int n=_samples.count();
  for(int i=0; i<n; i++) {
    Sample& s=_samples[i];
    if(s.x()>threshold) {
      s.setValid(false);
    }
  }
}

void SampleFilter::filterYMinimum(double threshold)
{
  TRACE;
  int n=_samples.count();
  for(int i=0; i<n; i++) {
    Sample& s=_samples[i];
    if(s.y()<threshold) {
      s.setValid(false);
    }
  }
}

void SampleFilter::filterYMaximum(double threshold)
{
  TRACE;
  int n=_samples.count();
  for(int i=0; i<n; i++) {
    Sample& s=_samples[i];
    if(s.y()>threshold) {
      s.setValid(false);
    }
  }
}

bool SampleFilter::lessThan(const Sample& s1, const Sample& s2)
{
  if(s1.frequency()<s2.frequency()) {
    return true;
  } else if(s1.frequency()>s2.frequency()) {
    return false;
  } else {
    if(s1.time()<s2.time()) {
      return true;
    } else {
      return false;
    }
  }
}

QVector<Histogram2D::Sample> SampleFilter::samples() const
{
  TRACE;
  QVector<Histogram2D::Sample> dest;
  int n=_samples.count();
  for(int i=0; i<n; i++) {
    const Sample& s=_samples.at(i);
    dest.append(s);
  }
  return dest;
}
