/***************************************************************************
**
**  This file is part of QGpGuiMath.
**
**  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: 2005-09-13
**  Copyright: 2005-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "SamplingParameterWidget.h"

namespace QGpGuiMath {

/*!
  \class SamplingParameterWidget SamplingParameterWidget.h
  \brief Widget to modify a SamplingParameters

  Maintains an internal SamplingParameters to provide correct transition
  from step to count mode.
*/
SamplingParameterWidget::SamplingParameterWidget(QWidget* parent)
    : QWidget(parent)
{
  TRACE;
  setupUi(this);

  _admissibleMin=-std::numeric_limits<double>::infinity();
  _admissibleMax=std::numeric_limits<double>::infinity();
}

void SamplingParameterWidget::setRangeOnly()
{
  TRACE;
  delete stepTypeLabel;
  stepTypeLabel=nullptr;
  delete stepType;
  stepType=nullptr;
  delete stepCountOption;
  stepCountOption=nullptr;
  delete stepCountValue;
  stepCountValue=nullptr;
}

void SamplingParameterWidget::updateAllFields()
{
  TRACE;
  _param.setRange(fromValue->value(), toValue->value());
  on_stepCountValue_valueChanged(stepCountValue->value());
  on_stepType_currentIndexChanged(stepType->currentIndex());
}

void SamplingParameterWidget::setPrecision(int digit)
{
  TRACE;
  fromValue->setDecimals(digit);
  toValue->setDecimals(digit);
}

void SamplingParameterWidget::setSingleStep(double s)
{
  TRACE;
  fromValue->setSingleStep(s);
  toValue->setSingleStep(s);
}

void SamplingParameterWidget::setAdmissibleRange(double min, double max)
{
  TRACE;
  if(min<max) {
    _admissibleMin=min;
    _admissibleMax=max;
  } else {
    _admissibleMin=max;
    _admissibleMax=min;
  }
  fromValue->setMinimum(_admissibleMin);
  toValue->setMinimum(_admissibleMin);
  fromValue->setMaximum(_admissibleMax);
  toValue->setMaximum(_admissibleMax);
  if(stepType) {
    if(_admissibleMax<0.0) {
      stepType->setCurrentIndex(1);
      stepType->setEnabled(false);
    } else {
      stepType->setEnabled(true);
    }
    if(stepType->currentIndex()==0 && _admissibleMin<0.0) {
      fromValue->setMinimum(pow(10, -fromValue->decimals()) );
      toValue->setMinimum(pow(10, -fromValue->decimals()) );
    }
  }
}

/*!
  Take the inverse of current values
*/
void SamplingParameterWidget::setInversed(bool inversed, bool inverseValues)
{
  TRACE;
  if(inversed!=_param.isInversed()) {
    if(inverseValues) {
      double min=fromValue->value();
      double max=toValue->value();
      fromValue->setValue(1.0/max);
      toValue->setValue(1.0/min);
    }
    _param.setInversed(inversed);
  }
}

void SamplingParameterWidget::on_fromValue_valueChanged(double val)
{
  TRACE;
  _param.setMinimum(val);
  parametersChanged();
}

void SamplingParameterWidget::on_toValue_valueChanged(double val)
{
  TRACE;
  _param.setMaximum(val);
  parametersChanged();
}

void SamplingParameterWidget::on_stepType_currentIndexChanged(int index)
{
  TRACE;
  if(index==0) {
    if(fromValue->minimum()<=0.0) {
      fromValue->setMinimum(pow(10, -fromValue->decimals()));
    }
    if(toValue->minimum()<=0.0) {
      toValue->setMinimum(pow(10, -fromValue->decimals()));
    }
    _param.setType(SamplingParameters::Log);
  } else {
    fromValue->setMinimum(_admissibleMin);
    toValue->setMinimum(_admissibleMin);
    _param.setType(SamplingParameters::Linear);
  }
  on_stepCountOption_currentIndexChanged(stepCountOption->currentIndex());
}

void SamplingParameterWidget::on_stepCountOption_currentIndexChanged(int index)
{
  TRACE;
  stepCountValue->blockSignals(true);
  if(index==0) {
    double minStep, delta;
    int ndec;
    if(stepType->currentIndex()==0) {
      delta=_param.maximum()/_param.minimum();
      minStep=::pow(delta, 1.0/static_cast<double>(10000-1));
      ndec=1-qFloor(::log10(minStep-1.0));
    } else {
      delta=_param.maximum()-_param.minimum();
      minStep=delta/static_cast<double>(10000-1);
      ndec=1-qFloor(::log10(minStep));
      stepCountValue->setDecimals(ndec<0 ? 0 : ndec);
      stepCountValue->setMinimum(minStep);
      stepCountValue->setMaximum(delta);
      stepCountValue->setSingleStep(::pow(10.0, ::floor(::log10(_param.step()-1.0)))-1.0);
      stepCountValue->setValue(_param.step());
    }
    stepCountValue->setDecimals(ndec<0 ? 0 : ndec);
    stepCountValue->setMinimum(minStep);
    stepCountValue->setMaximum(delta);
    stepCountValue->setSingleStep(::pow(10.0, ::floor(::log10(_param.step()-1.0)))-1.0);
    stepCountValue->setValue(_param.step());
  } else {
    stepCountValue->setDecimals(0);
    stepCountValue->setMinimum(1.0);
    stepCountValue->setMaximum(10000.0);
    stepCountValue->setValue(_param.count());
    stepCountValue->setSingleStep(1.0);
  }
  stepCountValue->blockSignals(false);
  emit parametersChanged();
}

void SamplingParameterWidget::on_stepCountValue_valueChanged(double val)
{
  TRACE;
  if(stepCountOption->currentIndex()==0) {
    _param.setStep(val);
  } else {
    _param.setCount(qRound(val));
  }
  emit parametersChanged();
}

void SamplingParameterWidget::setParameters(const SamplingParameters & param)
{
  TRACE;
  _param=param;
  fromValue->setValue(param.minimum());
  toValue->setValue(param.maximum());
  if(stepType) {
    stepType->setCurrentIndex(param.type()==SamplingParameters::Log ? 0 : 1);
    stepCountOption->setCurrentIndex(param.stepType()==SamplingParameters::Step ? 0 : 1);
  }
}

} // namespace QGpGuiMath
