/***************************************************************************
**
**  This file is part of ArrayCore.
**
**  ArrayCore 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.
**
**  ArrayCore 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-03-21
**  Copyright: 2017-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef FKPEAKS_H
#define FKPEAKS_H

#include <QGpCoreWave.h>

#include "ArrayCoreDLLExport.h"

namespace ArrayCore {

  class WaveNumberConverter;
  class FKParameters;
  class ArraySelection;

  class ARRAYCORE_EXPORT FKPeaks: private IncreaseStorage
  {
  public:
    FKPeaks();
    virtual ~FKPeaks();

    class Value
    {
    public:
      double frequency;
      double time;
      Mode::Polarization polarization;
      double slowness, azimuth, ellipticity, noise, power;
      bool valid;
    };

    void clear();
    int size() const {return IncreaseStorage::size();}
    bool add(const Point2D &k, double ell, double noise, double power,
             const WaveNumberConverter& conv, double minimumSlowness);
    void add(const FKPeaks& peaks);
    void sort();
    bool save(const QString &fileName, const FKParameters& param, const ArraySelection& array) const;
    bool load(const QString &fileName);

    void fillSlowness(Histogram2D * h, Mode::Polarization polarization) const;
    void fillWaveNumber(Histogram2D * h, Mode::Polarization polarization) const;
    void fillSlownessWaveNumber(Histogram2D * h, Mode::Polarization polarization) const;
    void fillAzimuth(Histogram2D * h, Mode::Polarization polarization) const;
    void fillEllipticity(Histogram2D * h) const;
    void commit(Histogram2D * h, Mode::Polarization polarization);
    void reset(Mode::Polarization polarization);

    void filterBelowWaveNumber(double minK);
    void horizontalSingleDirection(double angleTolerance);

    Value& valueAt(int index) const {return _values[index];}

    void setTimeReference(const DateTime& t) {_timeReference=t;}

    static const char * maxHeaderLine;
  private:
    class Azimuth {
    public:
      Azimuth(double v=0.0, int i=0) {value=v; index=i;}
      Azimuth(const Azimuth& o) {value=o.value; index=o.index;}

      double value;
      int index;
    };
    int validateSingleDirection(double rayleighAverage, const QVector<Azimuth>& rayleighValues,
                                double loveAverage, const QVector<Azimuth>& loveValues,
                                double angleTolerance);
    bool isSingleDirection(double average, const QVector<Azimuth>& values, double angleTolerance);
    void singleDirectionReport(double frequency, int notValidCount, int totalCount);

    static bool valueLessThan(Value * v1, Value * v2);
    virtual void reallocate();

    Value * _values;
    DateTime _timeReference;
    bool _full;
    Mutex _addLock;
    ReadWriteLock _dataLock;

    bool readHeader(QTextStream& s);
    bool read(QTextStream& s, Value& v);
  };

} // namespace ArrayCore

#endif // FKPEAKS_H

