/***************************************************************************
**
**  This file is part of GeopsyCore.
**
**  GeopsyCore 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.
**
**  GeopsyCore 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: 2017-10-20
**  Copyright: 2017-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "SignalProcessObject.h"

namespace GeopsyCore {

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

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  SignalProcessObject::SignalProcessObject(SignalProcess * p, QObject * parent)
    : QObject(parent)
  {
    TRACE;
    _process=p;
  }

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

  void SignalProcessObject::saveStep(QString tag)
  {
    TRACE;
    if(_process) {
      _process->saveStep(tag);
    }
  }

  void SignalProcessObject::restoreStep(QString tag)
  {
    TRACE;
    if(_process) {
      int index=_process->indexOfStep(tag);
      if(index>-1) {
        _process->restoreStep(index);
      }
    }
  }

  void SignalProcessObject::fastFourierTransform(QString signalType)
  {
    TRACE;
    if(_process) {
      bool ok=true;
      DoubleSignal::SignalType t=DoubleSignal::type(signalType, &ok);
      if(ok) {
        _process->fastFourierTransform(t);
      } else {
        App::log(tr("Bad signal type '%1', Fourier transform skipped.\n").arg(signalType));
      }
    }
  }

  bool SignalProcessObject::exportFile(QString filePath, bool useOriginalBaseName,
                                       QString format, int maximumSignalsPerFile,
                                       const QString& pickName)
  {
    TRACE;
    if(_process) {
      return _process->exportFile(filePath, useOriginalBaseName,
                                  SignalFileFormat::fromName(format),
                                  maximumSignalsPerFile,
                                  pickName);
    } else {
      return false;
    }
  }

  QVariant SignalProcessObject::header(int signalIndex, QString dataIndex)
  {
    TRACE;
    if(_process) {
      MetaDataIndex index(MetaDataFactory::instance()->index(dataIndex));
      return _process->header(signalIndex, index);
    } else {
      return false;
    }
  }

  void SignalProcessObject::setHeader(int signalIndex, QString dataIndex, QVariant value)
  {
    TRACE;
    if(_process) {
      MetaDataIndex index(MetaDataFactory::instance()->index(dataIndex));
      _process->setHeader(signalIndex, index, value);
    }
  }

  int SignalProcessObject::signalCount()
  {
    TRACE;
    if(_process) {
      return _process->signalCount();
    } else {
      return 0;
    }
  }

  void SignalProcessObject::selectSignals(int startIndex, int endIndex, QString tag)
  {
    TRACE;
    if(_process) {
      _process->selectSignals(startIndex, endIndex, tag);
    }
  }

  void SignalProcessObject::removeTrend()
  {
    TRACE;
    if(_process) {
      _process->removeTrend();
    }
  }

  void SignalProcessObject::subtractValue(double val)
  {
    TRACE;
    if(_process) {
      _process->subtractValue(val);
    }
  }

  void SignalProcessObject::subtractSignal(int index)
  {
    TRACE;
    if(_process) {
      _process->subtractSignal(index);
    }
  }

  void SignalProcessObject::subtractSignals(QString groupName)
  {
    TRACE;
    if(_process) {
      _process->subtractSignals(groupName);
    }
  }

  void SignalProcessObject::multiply(double val)
  {
    TRACE;
    if(_process) {
      _process->multiply(val);
    }
  }

  void SignalProcessObject::filter(QString method, QString band, double fmin, double fmax, double option)
  {
    TRACE;
    if(_process) {
      FilterParameters param;
      param.setMethod(method);
      param.setBand(band);
      param.setFrequencyRange(fmin, fmax);
      switch(param.method()) {
      case FilterParameters::Butterworth: {
          param.setOrder(qRound(option));
        }
        break;
      case FilterParameters::FrequencyWindow: {
          param.setWidth(option);
        }
        break;
      }
      _process->filter(param);
    }
  }

  void SignalProcessObject::whiten()
  {
    TRACE;
    if(_process) {
      _process->whiten();
    }
  }

  void SignalProcessObject::agc(double width)
  {
    TRACE;
    if(_process) {
      _process->agc(width);
    }
  }

  void SignalProcessObject::stddevClip(double factor)
  {
    TRACE;
    if(_process) {
      _process->stddevClip(factor);
    }
  }

  void SignalProcessObject::shift(double dt)
  {
    TRACE;
    if(_process) {
      _process->shift(dt);
    }
  }

  void SignalProcessObject::overSample(double factor)
  {
    TRACE;
    if(_process) {
      _process->overSample(factor);
    }
  }

  void SignalProcessObject::taper(QString range, QString taper)
  {
    TRACE;
    if(_process) {
      TimeRangeParameters rangeParam;
      rangeParam.fromShortString(range);
      WindowFunctionParameters  taperParam;
      taperParam.fromShortString(taper);
      _process->taper(rangeParam, taperParam);
    }
  }

  void SignalProcessObject::cut(QString range)
  {
    TRACE;
    if(_process) {
      TimeRangeParameters rangeParam;
      rangeParam.fromShortString(range);
      _process->cut(rangeParam);
    }
  }

  bool SignalProcessObject::merge()
  {
    TRACE;
    if(_process) {
      return _process->merge();
    } else {
      return false;
    }
  }

  bool SignalProcessObject::mergeStations()
  {
    TRACE;
    if(_process) {
      return _process->mergeStations();
    } else {
      return false;
    }
  }

  void SignalProcessObject::decimateAmplitude(int maxCount, double maxRef)
  {
    TRACE;
    if(_process) {
      _process->decimateAmplitude(maxCount, maxRef);
    }
  }

  void SignalProcessObject::decimateTime(int factor)
  {
    TRACE;
    if(_process) {
      _process->decimateTime(factor);
    }
  }

  void SignalProcessObject::waveletTransform(const MorletParameters& param)
  {
    TRACE;
    if(_process) {
      _process->waveletTransform(param);
    }
  }

  void SignalProcessObject::stalta(double tsta, double tlta)
  {
    TRACE;
    if(_process) {
      _process->stalta(tsta, tlta);
    }
  }

  void SignalProcessObject::discreteFourierTransform()
  {
    TRACE;
    if(_process) {
      _process->discreteFourierTransform();
    }
  }

  void SignalProcessObject::rotateComponents(bool z, double rotz, bool n, double rotn, bool e, double rote)
  {
    TRACE;
    if(_process) {
      RotateParameters param;
      RotateParameters::Axes a=(z ? RotateParameters::Vertical : RotateParameters::None) |
                               (n ? RotateParameters::North : RotateParameters::None) |
                               (e ? RotateParameters::East : RotateParameters::None);
      param.setAxes(a);
      param.setAngleAroundVertical(rotz);
      param.setAngleAroundNorth(rotn);
      param.setAngleAroundEast(rote);
      _process->rotateComponents(param);
    }
  }

  void SignalProcessObject::correlations(double maxDelay, int referenceIndex)
  {
    TRACE;
    if(_process) {
      _process->correlations(maxDelay, referenceIndex);
    }
  }

  void SignalProcessObject::normalizedCorrelations(double maxDelay, int referenceIndex)
  {
    TRACE;
    if(_process) {
      _process->normalizedCorrelations(maxDelay, referenceIndex);
    }
  }

  void SignalProcessObject::convolution(int referenceIndex)
  {
    TRACE;
    if(_process) {
      _process->convolution(referenceIndex);
    }
  }

  void SignalProcessObject::removeInstrumentalResponse(const InstrumentalResponse& sensor)
  {
    TRACE;
    if(_process) {
      _process->removeInstrumentalResponse(sensor);
    }
  }

} // namespace GeopsyCore

