/***************************************************************************
**
**  This file is part of QGpCoreMath.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2016-08-23
**  Copyright: 2016-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef CURVEPROXY_H
#define CURVEPROXY_H

#include <QGpCoreTools.h>

#include "Curve.h"
#include "QGpCoreMathDLLExport.h"

namespace QGpCoreMath {

  class QGPCOREMATH_EXPORT CurveProxy
  {
    TRANSLATIONS("CurveProxy")
  public:
    CurveProxy() {}
    virtual ~CurveProxy() {}

    virtual QString tag() const=0;
    virtual CurveProxy * clone() const=0;

    virtual int sampleCount() const=0;
    virtual void sort()=0;
    virtual double minimumX() const=0;
    virtual double maximumX() const=0;
    virtual double minimumY(const CurvePointOptions * pointOptions) const=0;
    virtual double maximumY(const CurvePointOptions * pointOptions) const=0;
    virtual bool isValid(int sample) const=0;
    virtual void setValid(int sample, bool v)=0;
    virtual void setName(const QString & n)=0;
    virtual QString name() const=0;
    virtual void addLog(QString s)=0;
    virtual QString log() const=0;
    virtual void cut(double min, double max, SamplingOptions options)=0;
    virtual void validate(double min, double max, bool value, SamplingOptions options)=0;
    virtual void resample(int n, double min, double max, double valX, double valY,
                          SamplingOptions options,
                          const CurvePointOptions * pointOptions)=0;
    virtual void resample(int n, double min, double max, SamplingOptions options)=0;
    virtual void average(const CurveProxy * o)=0;
    virtual int splitCount(double maxX, SamplingOptions options,
                           double maxErr, int minCount) const;
    virtual void split(const CurveProxy * o, int index,
                       double maxX, SamplingOptions options,
                       double maxErr, int minCount);

    virtual QVariant columnValue(int sample, int col) const=0;
    virtual void setColumnValue(int sample, int col, const QVariant & value)=0;

    virtual int columnCount() const=0;
    virtual QString columnName(int col) const=0;
    virtual QString columnUnit(int col) const=0;
    virtual QString columnTitle(int col) const;

    virtual int xAxisColumn() const=0;
    virtual int xAxisInversedColumn() const=0;
    virtual int yAxisColumn() const=0;
    virtual int yAxisInversedColumn() const=0;

    virtual QStringList columnFileTypes() const=0;
    virtual QVector<int> defaultColumnFileTypes() const=0;
    virtual QVector<int> savedColumns() const=0;

    void setComments(QString c);
    void save(QTextStream& s);
    virtual bool parse(ColumnTextIterator& it)=0;

    QString xName() const {return columnName(xAxisColumn());}
    QString xUnit() const {return columnUnit(xAxisColumn());}
    QString xTitle() const {return columnTitle(xAxisColumn());}
    QString xInversedName() const {return columnName(xAxisInversedColumn());}
    QString xInversedUnit() const {return columnUnit(xAxisInversedColumn());}
    QString xInversedTitle() const {return columnTitle(xAxisInversedColumn());}
    QString yName() const {return columnName(yAxisColumn());}
    QString yUnit() const {return columnUnit(yAxisColumn());}
    QString yTitle() const {return columnTitle(yAxisColumn());}
    QString yInversedName() const {return columnName(yAxisInversedColumn());}
    QString yInversedUnit() const {return columnUnit(yAxisInversedColumn());}
    QString yInversedTitle() const {return columnTitle(yAxisInversedColumn());}
  };

#define CURVEPROXY_BASICDECLARATIONS \
  virtual int sampleCount() const {return curve().count();} \
  virtual void sort() {curve().sort();} \
  virtual double minimumX() const; \
  virtual double maximumX() const; \
  virtual double minimumY(const CurvePointOptions * pointOptions) const; \
  virtual double maximumY(const CurvePointOptions * pointOptions) const; \
  virtual bool isValid(int sample) const {return curve()[sample].isValid();} \
  virtual void setValid(int sample, bool v) {curve()[sample].setValid(v);} \
  virtual void cut(double min, double max, SamplingOptions options) { \
    curve().cut(min, max, options); \
  } \
  virtual void validate(double min, double max, bool value, SamplingOptions options) { \
    curve().validate(min, max, value, options); \
  } \
  virtual void resample(int n, double min, double max, double valX, double valY, \
                        SamplingOptions options, \
                        const CurvePointOptions * pointOptions) { \
    curve().resample(n, min, max, valX, valY, options, pointOptions); \
  } \
  virtual void resample(int n, double min, double max, \
                        SamplingOptions options) { \
    curve().resample(n, min, max, options); \
  } \


#define CURVEPROXY_NAMEDECLARATIONS \
  virtual void setName(const QString & n) {curve().setName(n);} \
  virtual QString name() const {return curve().name();} \


#define CURVEPROXY_LOGDECLARATIONS \
  virtual void addLog(QString s) {curve().addLog(s);} \
  virtual QString log() const {return curve().log();} \

#define CURVEPROXY_BASICIMPLEMENTATIONS(className) \
  double className::minimumX() const { \
    int i=curve().minimumX(); \
    if(i>=0) { \
      return curve().at(i).x(); \
    } else { \
      return std::numeric_limits<double>::infinity(); \
    } \
  } \
  double className::maximumX() const { \
    int i=curve().maximumX(); \
    if(i>=0) { \
      return curve().at(i).x(); \
    } else { \
      return -std::numeric_limits<double>::infinity(); \
    } \
  } \
  double className::minimumY(const CurvePointOptions * pointOptions) const { \
    int i=curve().minimumY(0, pointOptions); \
    if(i>=0) { \
      return curve().at(i).y(pointOptions); \
    } else { \
      return std::numeric_limits<double>::infinity(); \
    } \
  } \
  double className::maximumY(const CurvePointOptions * pointOptions) const { \
    int i=curve().maximumY(0, pointOptions); \
    if(i>=0) { \
      return curve().at(i).y(pointOptions); \
    } else { \
      return -std::numeric_limits<double>::infinity(); \
    } \
  } \

} // namespace QGpCoreMath

#endif // CURVEPROXY_H

