/***************************************************************************
**
**  This file is part of QGpCompatibility.
**
**  QGpCompatibility 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.
**
**  QGpCompatibility 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: 2003-02-11
**  Copyright: 2003-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef COMPATAUTOCORRCURVES_H
#define COMPATAUTOCORRCURVES_H

#define CompatAUTOCORR_INVALID_VALUE -99

#include "QGpCompatibilityDLLExport.h"
#include "CompatDispersion.h"

namespace QGpCompatibility {

class QGPCOMPATIBILITY_EXPORT CompatAutocorrCurves: public CompatMultiModalFrequency
{
public:
  enum FrequencyRange {Complete,NoInitialFlat,FirstSlope};
  // Constructor: default constructor
  CompatAutocorrCurves();
  // Constructor
  CompatAutocorrCurves(int modesCount, int radiusCount, int omegasCount);
  // Copy constructor
  CompatAutocorrCurves(const CompatAutocorrCurves * o);
  // Copy constructor changing the number of modes
  CompatAutocorrCurves(const CompatAutocorrCurves * o,int modesCount);
  // Destructor: get rid of all unused memory
  virtual ~CompatAutocorrCurves();
  
  /* Calculate the autocorrelation curves from a dispersion curve for all possible modes
  Min(modesCount(),disp.modesCount())*/
  void calculate(CompatDispersion& disp);
  
  // Export curves to stream
  void toStream(FILE * f);
  // Prints the _radiusMin and _radiusMax to the binary stream (usually the autocorrreport)
  void radiusToReport(QDataStream& s) const;
  // Loads the _radiusMin and _radiusMax from the binary stream (usually the autocorrreport)
  void reportToRadius(QDataStream& s);
  // Prints the _autocorr to the binary stream (usually the autocorrreport)
  void valuesToReport(QDataStream& s) const;
  // Loads the _omega from the binary stream (usually the autocorrreport)
  void reportToOmega(QDataStream& s);
  // Loads the _autocorr from the binary stream (usually the autocorrreport)
  void reportToValues(QDataStream& s);
  // Copy all point of imode into a point vector and return the number of valid points
  int toPointVector(int imode,int iRadius,Point2D * pointList);
  // Copy all point of imode into a point vector and return the number of valid points
  int toDistancePointVector(int imode,int iomega,Point2D * pointList);
  // Set all autocorrelation curves to zero
  void resetAutocorr();
  
  // Returns the omega count for radius r and mode imode where autocorrelation is defined
  int omegasCount (int imode, int r) const;
  // Returns the omega count
  int omegasCount () const {return _omegasCount;}
  // Returns the radius count
  int radiusCount () const {return _radiusCount;}
  // Returns the radius min
  double radiusMin (int i) const {return _radiusMin[i];}
  // Returns the radius max
  double radiusMax (int i) const {return _radiusMax[i];}
  // Returns the radius average
  double radiusAverage (int i) const {return (_radiusMax[i]+_radiusMin[i])/2;}
  // Returns the radius average
  QVector<double> * radiusAverage () const;
  // Set Radius min and max
  void setRadius(QVector<double>& rmin,QVector<double>& rmax);
  void setRadius(CompatAutocorrCurves * o);
  void setRadius(QString radiusFile);
  void setRadius(int r, double rmin, double rmax)
  {_radiusMin[r]=rmin;_radiusMax[r]=rmax;}
  static int getRadiusCount(QString radiusFile);
  // Returns the ith autocorr of radius r and mode m
  double value(int i, int r,int m) const {return _values[m][r][i];}
  // Set autocorr of mode m, radius r and point i
  void setValue(int i, int r,int m, double value) {_values[m][r][i]=value;}
  // Set the range type for computations in calculate (by default it is complete)
  void setRangeType(FrequencyRange fr) {_rangeType=fr;}
  // Set all autocorr curves to invalid value
  void resetValues();
  void setRayleighModesCount(int rm) {
    if(rm<=_modesCount) _rayleighModesCount=rm;
  }
  uint rayleighModesCount() {return _rayleighModesCount;}
protected:
  friend class CompatAutocorrData;
  uint _rayleighModesCount;
  // Number of radius
  int _radiusCount;
  // Storage for radii min for each omega
  double * _radiusMin;
  // Storage for radii max for each omega
  double * _radiusMax;
  // Storage for calculated autocorrelations curves
  double *** _values;
  // Type of frequency range for computations in calculate()
  FrequencyRange _rangeType;
  // Allocates the storage for radius lists
  void allocatesRadius();
  // Delete _values (called by destructor)
  void deleteValues();
  // Allocates the storage for calculated slownesses
  void allocatesValues();
};

} // namespace QGpCompatibility

#endif // COMPATAUTOCORRCURVES_H
