/***************************************************************************
**
**  This file is part of DinverCore.
**
**  DinverCore 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.
**
**  DinverCore 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: 2014-09-02
**  Copyright: 2014-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#ifndef QUADRATICCONDITION_H
#define QUADRATICCONDITION_H

#include <QGpCoreTools.h>

#include "AbstractCondition.h"
#include "DinverCoreDLLExport.h"

namespace DinverCore {

class DINVERCORE_EXPORT QuadraticCondition : public AbstractCondition
{
public:
  QuadraticCondition(double coef1, Parameter * p1,
                     double coef2, Parameter * p2, Type type, double constant);
  QuadraticCondition(double coef1, Parameter * p1,
                     double coef2, Parameter * p2,
                     double coef3, Parameter * p3, Type type, double constant);
  ~QuadraticCondition();

  virtual bool operator==(const AbstractCondition& o) const;

  virtual const QString& xml_tagName() const {return xmlQuadraticConditionTag;}
  static const QString xmlQuadraticConditionTag;

  inline virtual void getLimits(int paramIndex, double& min, double& max) const;
  virtual bool adjustRanges();
  virtual void humanInfo() const;
protected:
  virtual uint internalChecksum() const;
  virtual void xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const;
  virtual XMLMember xml_member(XML_MEMBER_ARGS);
  virtual bool xml_setProperty(XML_SETPROPERTY_ARGS);
private:
  Type _type;
  double * _factors;
  double _constant;
};

} // namespace DinverCore

#include "Parameter.h"

namespace DinverCore {

inline void QuadraticCondition::getLimits(int paramIndex, double& min, double& max) const
{
  TRACE;
  if(min<0.0) {
    App::log(tr("Quadratic condition cannot be used with negative parameters, skipping condition.\n") );
    return;
  }
  double threshold=_constant;
  double v;
  int i;
  for(i=count()-1; i>paramIndex; i--) {
    v=parameter(i).realValue();
    threshold-=_factors[i]*v*v;
  }
  for(i--; i>=0; i--) {
    v=parameter(i).realValue();
    threshold-=_factors[i]*v*v;
  }
  threshold=sqrt(threshold);
  switch (_type) {
  case LessThan:
    if(threshold<max) {
      max=threshold;
    }
    break;
  case GreaterThan:
    if(threshold>min) {
      min=threshold;
    }
    break;
  case NoCondition:
    break;
  }
}

} // namespace DinverCore

#endif // QUADRATICCONDITION_H
