/***************************************************************************
**
**  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: 2013-02-20
**  Copyright: 2013-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "CurveProperties.h"
#include "CurveBrowser.h"
#include "CurveBrowserDelegate.h"
#include "CurveBrowserItem.h"

namespace QGpGuiMath {

  /*!
    \class CurveProperties CurveProperties.h
    \brief Brief description of class still missing

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  CurveProperties::CurveProperties(QWidget * parent)
    : QWidget(parent)
  {
    TRACE;
    setupUi(this);

    CurveBrowserDelegate * delegate=new CurveBrowserDelegate(this);
    curveTable->setItemDelegate(delegate);
    connect(delegate, SIGNAL(dataChanged()), this, SLOT(applyAllSelected()));

    curveTable->setSelectionBehavior(QAbstractItemView::SelectItems);
    curveTable->setSelectionMode(QAbstractItemView::ExtendedSelection);
    curveTable->setEditTriggers(QAbstractItemView::AllEditTriggers);
    curveTable->resizeColumnsToContents();

    _proxy=nullptr;
    _line=nullptr;
    _currentLayer=nullptr;
  }

  /*!
    Description of destructor still missing
  */
  CurveProperties::~CurveProperties()
  {
    TRACE;
    Settings::setColumnWidth(curveTable, _proxy->tag());
    delete _proxy;
  }

  void CurveProperties::setProxy(CurveProxy * proxy)
  {
    _proxy=proxy;
    CurveBrowserItem * model=new CurveBrowserItem(_proxy, this);
    curveTable->setModel(model);
    curveName->setText(proxy->name());
    Settings::columnWidth(curveTable, _proxy->tag());
    connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this, SIGNAL(curveModified()));
  }

  void CurveProperties::setEditable(bool e)
  {
    curveName->setEnabled(e);
    CurveBrowserItem * item=qobject_cast<CurveBrowserItem *>(curveTable->model());
    item->setEditable(e);
  }

  void CurveProperties::setLine(AbstractLine * line)
  {
    _line=line;
    visibleBut->blockSignals(true);
    visibleBut->setChecked(_line->isVisible());
    visibleBut->blockSignals(false);
  }

  void CurveProperties::setCurveVisible(bool v)
  {
    visibleBut->setChecked(v);
  }

  void CurveProperties::applyAllSelected()
  {
    TRACE;
    QAbstractItemModel& model=* curveTable->model();
    QModelIndex curIndex=curveTable->currentIndex();
    QModelIndexList l=curveTable->selectionModel()->selectedRows();
    if(l.count()>1) {
      QVariant val=model.data(curIndex);
      QModelIndex index;
      foreach(index, l) {
        model.setData(model.index(index.row(), curIndex.column()), val);
      }
    }
    _currentLayer->deepUpdate();
    emit curveModified();
  }

  void CurveProperties::beginCurveChange()
  {
    TRACE;
    CurveBrowserItem * model=static_cast<CurveBrowserItem *>(curveTable->model());
    model->beginCurveChange();
  }

  void CurveProperties::endCurveChange()
  {
    TRACE;
    CurveBrowserItem * model=static_cast<CurveBrowserItem *>(curveTable->model());
    model->endCurveChange();
    curveName->setText(_proxy->name());
    _currentLayer->deepUpdate();
    emit curveModified();
  }

  void CurveProperties::resample(int n, double minimum, double maximum, SamplingOptions options, bool distance)
  {
    TRACE;
    if(minimum>maximum) {
      qSwap(minimum, maximum);
    }
    QString sMode, unit;
    if(options & LogScale) {
      sMode=tr("log(%1)").arg(_proxy->xName());
      unit=_proxy->xUnit();
    } else if(options & InversedScale) {
      sMode=_proxy->xInversedName();
      unit=_proxy->xInversedUnit();
    } else {
      sMode=_proxy->xName();
      unit=_proxy->xUnit();
    }
    beginCurveChange();
    if(distance) {
      _proxy->resample(n, minimum, maximum,
                       0.5*(_proxy->minimumX()+_proxy->maximumX()),
                       0.5*(_proxy->minimumY(_currentLayer->pointOptions())+
                            _proxy->maximumY(_currentLayer->pointOptions())),
                       options, _currentLayer->pointOptions());
      _proxy->addLog(tr( "Resampled with constant distance along curve[%1] from %2 %3 to %4 %5 with %6 samples\n")
                     .arg(sMode).arg(minimum).arg(unit).arg(maximum).arg(unit).arg(n));
    } else {
      _proxy->resample(n, minimum, maximum, options);
      _proxy->addLog(tr("Resampled on a %1 scale from %2 %3 to %4 %5 with %6 samples\n")
                     .arg(sMode).arg(minimum).arg(unit).arg(maximum).arg(unit).arg(n));
    }
    endCurveChange();
  }

  /*!

  */
  void CurveProperties::cut(double minimum, double maximum, SamplingOptions options)
  {
    TRACE;
    if(minimum>maximum) {
      qSwap(minimum, maximum);
    }
    QString unit;
    options|=Interpole;
    if(options & InversedScale) {
      unit=_proxy->xInversedUnit();
    } else {
      unit=_proxy->xUnit();
    }
    beginCurveChange();
    _proxy->cut(minimum, maximum, options);
    _proxy->addLog(tr("Cut from %2 %3 to %4 %5\n")
                   .arg(minimum).arg(unit).arg(maximum).arg(unit) );
    endCurveChange();
  }

  /*!

  */
  void CurveProperties::validate(double minimum, double maximum, SamplingOptions options, bool value)
  {
    TRACE;
    if(minimum>maximum) {
      qSwap(minimum, maximum);
    }
    QString unit;
    if(options & InversedScale) {
      unit=_proxy->xInversedUnit();
    } else {
      unit=_proxy->xUnit();
    }
    beginCurveChange();
    _proxy->validate(minimum, maximum, value, options);
    _proxy->addLog(tr("Set valid to %1 from %2 %3 to %4 %5\n")
                   .arg(value).arg(minimum).arg(unit).arg(maximum).arg(unit) );
    endCurveChange();
  }

  /*!

  */
  void CurveProperties::smooth(double minimum, double maximum, SamplingOptions options)
  {
    TRACE;
    QString sMode, unit;
    if(options & LogScale) {
      sMode=tr("log(%1)").arg(_proxy->xName());
      unit=_proxy->xUnit();
    } else if(options & InversedScale) {
      sMode=_proxy->xInversedName();
      unit=_proxy->xInversedUnit();
    } else {
      sMode=_proxy->xName();
      unit=_proxy->xUnit();
    }
    beginCurveChange();
    // TODO
    //_proxy->smooth(minimum, maximum, options);
    _proxy->addLog(tr("Smoothed on a %1 scale from %2 %3 to %4 %5\n")
                   .arg(sMode).arg(minimum).arg(unit).arg(maximum).arg(unit));
    endCurveChange();
  }

  void CurveProperties::on_curveName_textChanged(QString text)
  {
    TRACE;
    _proxy->setName(text);
    emit nameChanged(text);
  }

  void CurveProperties::on_visibleBut_toggled(bool checked)
  {
    TRACE;
    if(_line->isVisible()!=checked) {
      LayerLocker ll(_currentLayer);
      _line->setVisible(checked);
      _currentLayer->deepUpdate();
    }
  }

} // namespace QGpGuiMath
