/***************************************************************************
**
**  This file is part of GeopsyGui.
**
**  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: 2010-02-28
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "SignalLayerControls.h"
#include "AbstractGraphicWindow.h"

namespace GeopsyGui {

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

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  SignalLayerControls::SignalLayerControls(SignalLayer * signalLayer, QWidget * parent)
      : QWidget(parent)
  {
    TRACE;
    _referenceOverlap=-1;
    _referenceTimeRange=-1;
    _signalLayer=signalLayer;
    connect(_signalLayer, SIGNAL(propertiesChanged()), this, SLOT(propertiesChanged()));
    setupUi(this);
    propertiesChanged();
  }

  /*!
    Description of destructor still missing
  */
  SignalLayerControls::~SignalLayerControls()
  {
    TRACE;
  }

  /*!
    Called whenever properties of signal layer are edited by the user
  */
  void SignalLayerControls::propertiesChanged()
  {
    TRACE;
    normalizationCombo->blockSignals(true);
    switch(_signalLayer->normalize()) {
    case SignalLayer::NormalizeAll:
    case SignalLayer::NormalizeValue:
      normalizationCombo->setCurrentIndex(0);
      break;
    case SignalLayer::NormalizeOne:
      normalizationCombo->setCurrentIndex(1);
      break;
    case SignalLayer::NormalizeVisibleAll:
      normalizationCombo->setCurrentIndex(2);
      break;
    case SignalLayer::NormalizeVisibleOne:
      normalizationCombo->setCurrentIndex(3);
      break;
    }
    normalizationCombo->blockSignals(false);
    offsetCombo->blockSignals(true);
    switch(_signalLayer->offset()) {
    case SignalLayer::NoOffset:
      offsetCombo->setCurrentIndex(0);
      break;
    case SignalLayer::GlobalOffset:
      offsetCombo->setCurrentIndex(1);
      break;
    case SignalLayer::VisibleOffset:
      offsetCombo->setCurrentIndex(2);
      break;
    }
    offsetCombo->blockSignals(false);
  }

  void SignalLayerControls::updateSignals()
  {
    TRACE;
    AxisWindow * w=_signalLayer->graph();
    if(w->proxy()) {
      w->proxy()->setValues();
    }
    _signalLayer->deepUpdate();
  }

  void SignalLayerControls::on_timeSlider_sliderPressed()
  {
    TRACE;
    AxisWindow * w=_signalLayer->graph();
    _referenceTimeRange=w->xAxis()->visibleMaximum()-w->xAxis()->visibleMinimum();
  }

  void SignalLayerControls::on_timeSlider_sliderMoved(int value)
  {
    TRACE;
    AxisWindow * w=_signalLayer->graph();
    double factor=pow(1.05, -value);
    double currentTimeRange=w->xAxis()->visibleMaximum()-w->xAxis()->visibleMinimum();
    double newTimeRange=_referenceTimeRange*factor;
    if(newTimeRange<currentTimeRange) {
      double newVisibleMinimum=w->xAxis()->visibleMinimum()+(currentTimeRange-newTimeRange)/2;
      w->zoomIn(newVisibleMinimum, w->yAxis()->visibleMinimum(),
                newVisibleMinimum+newTimeRange, w->yAxis()->visibleMaximum());
    } else {
      w->zoomOut();
      if(newTimeRange<w->xAxis()->maximum()-w->xAxis()->minimum()) {
        while(w->xAxis()->visibleMaximum()-w->xAxis()->visibleMinimum()<newTimeRange) {
          w->zoomOut();
        }
      }
    }
    updateSignals();
  }

  void SignalLayerControls::on_timeSlider_sliderReleased()
  {
    TRACE;
    _referenceTimeRange=-1;
    timeSlider->setValue(0);
  }

  void SignalLayerControls::on_amplitudeSlider_sliderPressed()
  {
    TRACE;
    _referenceOverlap=_signalLayer->overlap();
  }

  void SignalLayerControls::on_amplitudeSlider_sliderMoved(int value)
  {
    TRACE;
    double factor=pow(1.05, value);
    _signalLayer->setOverlap(_referenceOverlap*factor);
    if(_signalLayer->baseLineCount()==1) {
      AxisWindow * plot=_signalLayer->graph();
      static_cast<AbstractGraphicWindow* >(plot->parent())->setLimits();
      plot->updateInternalGeometry();
      plot->update();
    }
    updateSignals();
  }

  void SignalLayerControls::on_amplitudeSlider_sliderReleased()
  {
    TRACE;
    _referenceOverlap=-1;
    amplitudeSlider->setValue(0);
  }

  void SignalLayerControls::on_normalizationCombo_currentIndexChanged(int index)
  {
    TRACE;
    switch(index) {
    case 0:
      _signalLayer->setNormalize(SignalLayer::NormalizeAll);
      break;
    case 1:
      _signalLayer->setNormalize(SignalLayer::NormalizeOne);
      break;
    case 2:
      _signalLayer->setNormalize(SignalLayer::NormalizeVisibleAll);
      break;
    case 3:
      _signalLayer->setNormalize(SignalLayer::NormalizeVisibleOne);
      break;
    default:
      ASSERT(false);
      break;
    }
    updateSignals();
  }

  void SignalLayerControls::on_offsetCombo_currentIndexChanged(int index)
  {
    TRACE;
    switch(index) {
    case 0:
      _signalLayer->setOffset(SignalLayer::NoOffset);
      break;
    case 1:
      _signalLayer->setOffset(SignalLayer::GlobalOffset);
      break;
    case 2:
      _signalLayer->setOffset(SignalLayer::VisibleOffset);
      break;
    default:
      ASSERT(false);
      break;
    }
    updateSignals();
  }

} // namespace GeopsyGui
