/***************************************************************************
**
**  This file is part of HVGui.
**
**  HVGui 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.
**
**  HVGui 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: 2020-05-04
**  Copyright: 2020
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include <HVCore.h>

#include "CurveResultWidget.h"

namespace HVGui {

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

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  CurveResultWidget::CurveResultWidget(QWidget * parent)
    : AbstractResultWidget(parent)
  {
    TRACE;

    AxisWindow * g=new AxisWindow;
    g->setObjectName("result");
    g->setAnchor(GraphicObject::TopRight);
    g->setGeometry(9.0, 1.0, 7.5, 7.5, Axis::AxisSize);
    g->xAxis()->setFrequency();
    g->yAxis()->setNumberType('e');

    _t10Layer=new ParallelBands(g);   // T10
    _t10Layer->setObjectName("T10");

    _peakLayer=new ParallelBands(g);  // Frequency bands
    _peakLayer->setObjectName("f0");

    _windowsLayer=new XUniqueYColorLines(g);
    _windowsLayer->setObjectName("Windows");
    _windowsLayer->setLineWeight(0.02);
    _windowsLayer->addTrackingAction(tr("Reject time windows"), 0, tr("Rejected time windows are set in gray. "
                                     "Hit 'clear' to effectively remove them from the processing."));

    PlotLine2D * line;

    _averageLayer=new LineLayer(g);
    _averageLayer->setObjectName("Average");
    line=new PlotLine2D;
    line->setPen(Pen(Qt::black, 0.6, Qt::SolidLine));
    line->setSymbol(Symbol());
    _averageLayer->setReferenceLine(line);
    _averageLayer->addLine();

    _stddevLayer=new LineLayer(g);
    _stddevLayer->setObjectName("Stddev");
    line=static_cast<PlotLine2D *>(line->clone());
    line->setPen(Pen(Qt::black, 0.6, Qt::DashLine));
    _stddevLayer->setReferenceLine(line);
    _stddevLayer->addLine();
    _stddevLayer->addLine();

    _noiseModelLayer=nullptr;

    g->updateExternalGeometry();
    g->updateGeometry();
    addObject(g);
  }

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

  void CurveResultWidget::setValues(AbstractResults * res)
  {
    TRACE;
    AbstractResultWidget::setValues(res);
    connect(_windowsLayer, SIGNAL(dataSelected(int, const QVector<int>*)),
            _values, SLOT(blackWindows(int, const QVector<int>*)));
    connect(values(), SIGNAL(peakChanged()), this, SIGNAL(peakChanged()));
  }

  void CurveResultWidget::setValueTitle(const QString& t)
  {
    AxisWindow * g=_t10Layer->graph();
    g->yAxis()->setTitle(t);
  }

  const QString& CurveResultWidget::valueTitle() const
  {
    TRACE;
    AxisWindow * g=_t10Layer->graph();
    return g->yAxis()->title();
  }

  void CurveResultWidget::restoreMakeUp(const QString& fileName)
  {
    AxisWindow * g=_t10Layer->graph();
    return g->restoreMakeUp(fileName);
  }

  void CurveResultWidget::addFrequencyBands(ParallelBands * layer, const CurveResults * res, int index)
  {
    TRACE;
    double f=res->peak(index, CurveResults::PeakFrequency);
    layer->addBand(res->peakMinimum(index), f, QColor(Qt::lightGray));
    layer->addBand(f, res->peakMaximum(index), QColor(Qt::gray));
  }

  void CurveResultWidget::showValues()
  {
    TRACE;
    AxisWindow * g=_t10Layer->graph();
    _t10Layer->clear();
    _t10Layer->addBand(-std::numeric_limits<double>::infinity(), 10.0/values()->averageWindowLength(),
                       QBrush(QColor( 220, 154, 179), Qt::BDiagPattern));

    _peakLayer->clear();
    int n=values()->peakCount();
    for(int i=0; i<n; i++) {
      addFrequencyBands(_peakLayer, values(), i);
    }

    _windowsLayer->setData(values()->windows());

    static_cast<PlotLine2D *>(_averageLayer->line(0))->setCurve(values()->average());

    static_cast<PlotLine2D *>(_stddevLayer->line(0))->setCurve(values()->stddevLow());
    static_cast<PlotLine2D *>(_stddevLayer->line(1))->setCurve(values()->stddevHigh());

    g->deepUpdate();
  }

  void CurveResultWidget::setPetersonNoiseModel(const SamplingParameters &sampling, const QString &unit)
  {
    TRACE;
    if(!_noiseModelLayer) {
      _noiseModelLayer=new LineLayer(_t10Layer->graph());
      _noiseModelLayer->setObjectName("NewNoiseModel");
      PlotLine2D * line=new PlotLine2D;
      line->setPen(Pen(Qt::gray, 1.0, Qt::DotLine));
      _noiseModelLayer->setReferenceLine(line);
      _noiseModelLayer->addLine();
      _noiseModelLayer->addLine();
    }

    LayerLocker ll(_noiseModelLayer);
    NewNoiseModel m;

    PlotLine2D *low=static_cast<PlotLine2D *>(_noiseModelLayer->line(0));
    PlotLine2D *high=static_cast<PlotLine2D *>(_noiseModelLayer->line(1));

    if(unit=="m/s") {
      low->setCurve(m.curve(NewNoiseModel::LowVelocity, sampling));
      high->setCurve(m.curve(NewNoiseModel::HighVelocity, sampling));
    } else if(unit=="m/s^2") {
      low->setCurve(m.curve(NewNoiseModel::LowAcceleration, sampling));
      high->setCurve(m.curve(NewNoiseModel::HighAcceleration, sampling));
    } else if(unit=="m") {
      low->setCurve(m.curve(NewNoiseModel::LowDisplacement, sampling));
      high->setCurve(m.curve(NewNoiseModel::HighDisplacement, sampling));
    } else {
      App::log(tr("Cannot compute New Noise Model for 'count' and 'V' units, fix unit factors in signal headers.\n") );
      low->clear();
      high->clear();
    }
  }

  void CurveResultWidget::setLimits(const SamplingParameters& x, double maxY)
  {
    TRACE;
    AxisWindow * g=_t10Layer->graph();
    g->xAxis()->setRange(x.minimum(), x.maximum());
    g->yAxis()->setRange(0.0, maxY);
  }

  double CurveResultWidget::maximumY() const
  {
    TRACE;
    AxisWindow * g=_t10Layer->graph();
    return g->yAxis()->maximum();
  }

} // namespace HVGui

