/***************************************************************************
**
**  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: 2007-02-26
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "AbstractCondition.h"
#include "Parameter.h"

namespace DinverCore {

/*!
  \class AbstractCondition AbstractCondition.h
  \brief Abstract class to define an arbitrary condition between parameters

  Implement function getLimits() to define your own type of condition
*/

const QString AbstractCondition::xmlAbstractConditionTag="AbstractCondition";

bool AbstractCondition::operator==(const AbstractCondition& o) const
{
  TRACE;
  return _paramList==o._paramList;
}

/*!
  \fn void getLimits(int paramIndex, double& min, double& max) const
  Adjust \a min or/and \a max to fulfill the condition. All parameters of the model are supposed to be fixed except \a paramIndex.
  Hence, \a min and \a max correspond to parameter \a paramIndex.
*/

/*!
  \fn bool AbstractCondition::adjustRanges()
  Return true if original ranges of parameter are touched. Ranges can be reduced, never enlarged
*/

/*!
  Return a number that uniquely identify this condition.

  \sa internalChecksum()
*/
uint AbstractCondition::checksum() const
{
  TRACE;
  uint cs=0;
  for(QList<Parameter *>::const_iterator it=_paramList.begin(); it!=_paramList.end(); it++ ) {
    cs += qHash((*it)->name());
  }
  cs+=internalChecksum();
  return cs;
}

void AbstractCondition::xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const
{
  TRACE;
  Q_UNUSED(context)
  for(QList<Parameter *>::const_iterator it=_paramList.begin(); it!=_paramList.end(); it++ ) {
    writeProperty(s, "param", (*it)->name());
  }
}

XMLMember AbstractCondition::xml_member(XML_MEMBER_ARGS)
{
  TRACE;
  Q_UNUSED(attributes)
  Q_UNUSED(context)
  if(tag=="param" )
    return XMLMember(0);
  else
    return XMLMember(XMLMember::Unknown);
}

bool AbstractCondition::xml_setProperty(XML_SETPROPERTY_ARGS)
{
  TRACE;
  Q_UNUSED(tag)
  Q_UNUSED(attributes)
  Q_UNUSED(context)
  switch (memberID) {
  case 0:
    _paramNameList.append(content.toString());
    return true;
  default:
    return false;
  }
}

QString AbstractCondition::toString(Type t)
{
  switch(t) {
  case LessThan:
    break;
  case GreaterThan:
    return "GreaterThan";
  case NoCondition:
    return "NoCondition";
  }
  return "LessThan";
}

AbstractCondition::Type AbstractCondition::fromString(QString t, bool& ok)
{
  if(!t.isEmpty()) {
    switch(t[0].unicode()) {
    case 'L':
      if(t=="LessThan") {
        return LessThan;
      }
      break;
    case 'G':
      if(t=="GreaterThan") {
        return GreaterThan;
      }
      break;
    case 'N':
      if(t=="NoCondition") {
        return NoCondition;
      }
      break;
    default:
      break;
    }
  }
  ok=false;
  return NoCondition;
}

} // namespace DinverCore
