/***************************************************************************
**
**  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: 2017-06-12
**  Copyright: 2017-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef DENSITIES_H
#define DENSITIES_H

#include <QGpCoreMath.h>

#include "QGpCoreStatDLLExport.h"

namespace QGpCoreStat {

  class QGPCORESTAT_EXPORT Densities
  {
  public:
    Densities();
    Densities(int count);
    Densities(const Densities& o);
    ~Densities();

    void operator=(const Densities& o);

    int count() const {return _count;}

    inline void setDensity(int index, double mean, double stddev);
    const GaussDistribution& density(int index) const {return _densities[index];}

    void setWeight(int index, double w) {_weights[index]=w;}
    double weight(int index) const {return _weights[index];}

    double qualityFactor(int index) const;
    void sort();
    void filterQualityFactor(double min);
    void filterWeight(double min);
    void filterMaxima(double stddevFactor);
    void merge();
    void excludeMerge();
    void filterRange(double min, double max);
    void bestQualityFactors(int maxCount);
    void bestWeights(int maxCount);
    void intersection(const Densities& o);
    int indexOf(double weight, const GaussDistribution& density) const;

    void printDebug() const;
    QString humanInfo(const QString prefix) const;
    double density(double x) const;
    double cumulativeDensity(double x) const;
  private:
    class SortIndex
    {
    public:
      SortIndex() {_i=0; _parent=nullptr;}
      SortIndex(Densities * parent, int i) {_i=i; _parent=parent;}
      SortIndex(const SortIndex& o) {_i=o._i; _parent=o._parent;}

      int _i;
      Densities * _parent;
    };
    static bool lessThan(const SortIndex& i1, const SortIndex& i2);
    static void beginFilter(double *& newWeights, GaussDistribution *& newDensities, int newDensityCount);
    void endFilter(double * newWeights, GaussDistribution * newDensities, int newDensityCount);

    int _count;
    GaussDistribution * _densities;
    double * _weights;
  };

  inline void Densities::setDensity(int index, double mean, double stddev)
  {
    _densities[index].setMean(mean);
    _densities[index].setStddev(stddev);
  }

} // namespace QGpCoreStat

#endif // DENSITIES_H

