/***************************************************************************
**
**  This file is part of hvtfa.
**
**  hvtfa 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.
**
**  hvtfa 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: 2007-05-31
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**    Marc Wathelet (ISTerre, Grenoble, France)
**    Miriam Kristekova (Geophysical Institute, Academy of Sciences, Bratislava, Slovak Republic)
**
***************************************************************************/

#include <GeopsyCore.h>
#include <QGpGuiTools.h>
#include "ToolHVTFA.h"
#include "ToolHVTFAd.h"
#include "HVTFAStationSignals.h"
#include "HVTFALoop.h"

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

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
ToolHVTFA::ToolHVTFA(QWidget * parent)
    : AbstractToolWidget(parent, 0)
{
  TRACE;
  _iterator=0;
  _loop=0;

  QVBoxLayout * baseLayout=new QVBoxLayout(this);
  _d=new ToolHVTFAd(this);
  baseLayout->addWidget(_d);

  connect(_d->startBut, SIGNAL(clicked()), this, SLOT(start()));
  connect(_d->stopBut, SIGNAL(clicked()), this, SLOT(stop()));
  connect(_d->loadParam, SIGNAL(clicked()), this, SLOT(loadLogParameters()));
  _d->stopBut->setEnabled(false);

  setWindowIcon(QIcon(":hvtfa-22x22.png"));
  setObjectName("ToolHVTFA");
}

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

void ToolHVTFA::updateAllFields()
{
  TRACE;
  _d->timeLimits->updateAllFields();
  _d->freqSamp->updateAllFields();
  _d->wavelet->updateAllFields();
}

bool ToolHVTFA::initStations(SubSignalPool * subPool)
{
  TRACE;
  GeopsyCoreEngine::instance()->showMessage(subPool->database(), tr("Initializing stations..."));
  QString str=tr("H/V TFA toolbox - ")+subPool->name();
  setWindowTitle(str);
  // Sort station for convenience
  StationSignals::organizeSubPool(subPool);
  // Create all orignals stations
  QString log;
  if(!_stationSignals.addSignals(subPool) ||
      !_stationSignals.hasAllComponents() ||
      _stationSignals.components()!=StationSignals::AllComponent) {
    if(_stationSignals.components()!=StationSignals::AllComponent) {
      log+=tr("Detected less than 3 components\n");
    }
    Message::warning(MSG_ID, tr("Checking stations"), log, Message::cancel());
    return false;
  }
  int n=_stationSignals.count();
  for(int i=0; i<n; i++) {
    StationSignals * statSigs=_stationSignals.at(i);
    _stations.append(new HVTFAStationSignals(statSigs));
  }
  _d->timeLimits->setSubPool(subPool);
  return true;
}

void ToolHVTFA::start()
{
  TRACE;
  if(_iterator || subPoolLocked()) return;
  ASSERT(!_loop);
  _d->getParameters(_param);
  _iterator=new HVTFAIterator(&_stations, &_param.timeRange());
  _terminated=false;
  _d->stopBut->setEnabled(true);
  _d->startBut->setEnabled(false);
  _log.clear();
  _log+="### Parameters ###\n";
  _log+=_param.toString();
  _log+="### End Parameters ###\n";
  lockSubPool();
  startLoop();
}

void ToolHVTFA::startLoop()
{
  TRACE;
  if(!_terminated) {
    if(!_iterator->atEnd()) {
      HVTFAStationSignals * stat=_stations.at(_iterator->stationIndex());
      GeopsyCoreEngine::instance()->showMessage(subPool()->database(), tr("Station %1 (range %2/%3): computing fourier spectra")
                              .arg(stat->originalSignals()->name())
                              .arg(_iterator->rangeIndex()+1)
                              .arg(_iterator->rangeCount()));
      if(_loop) {
        _loop->deleteLater();
      }
      _loop=stat->createLoop(_iterator->range(), &_param);
      if(_loop->openMaxFile(_iterator->rangeIndex()==0)) {
        _loop->_stationName=tr("%1, range %2/%3")
                            .arg(stat->originalSignals()->name())
                            .arg(_iterator->rangeIndex()+1)
                            .arg(_iterator->rangeCount());
        if(_iterator->rangeIndex()==0) {
          stat->writeLog(_param.outputDirectory(), _log);
        }
        connect(_loop, SIGNAL(finished()), this, SLOT(startLoop()));
        _loop->start(0, _param.frequencySampling().count());
        _iterator->next();
        return;
      } else {
        Message::warning(MSG_ID, tr("H/V Time Frequency Analysis"),
                         tr("Cannot open file %1 for writing").arg(_loop->_fdotmax.fileName()),
                         Message::cancel(), true);
      }
    }
  }
  unlockSubPool();
  _d->stopBut->setEnabled(false);
  _d->startBut->setEnabled(true);
  _loop->deleteLater();
  _loop=0;
  delete _iterator;
  _iterator=0;
  GeopsyCoreEngine::instance()->showMessage(subPool()->database(), tr("H/V TFA completed"));
}

void ToolHVTFA::waitFinished()
{
  TRACE;
  while(_iterator && !_iterator->atEnd()) {
    ASSERT(_loop);
    _loop->waitFinished();
  }
}

void ToolHVTFA::stop()
{
  TRACE;
  _terminated=true;
  if(_loop) {
    _loop->terminate();
    GeopsyCoreEngine::instance()->showMessage(subPool()->database(), tr("HVTFA computation stopped"));
  }
}

AbstractParameters * ToolHVTFA::parameters(AbstractParameters * param) const
{
  TRACE;
  if(!param) {
    param=new HVTFAParameters;
  }
  _d->getParameters(*static_cast<HVTFAParameters *>(param));
  return param;
}

void ToolHVTFA::setParameters(const AbstractParameters * param)
{
  TRACE;
  _d->setParameters(*static_cast<const HVTFAParameters *>(param));
}
