/***************************************************************************
**
**  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-06-01
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**    Miriam Kristekova (Geophysical Institute, Academy of Sciences, Bratislava, Slovak Republic)
**
***************************************************************************/

#include <QGpGuiTools.h>
#include "HVTFAStationSignals.h"
#include "HVTFAParameters.h"
#include "HVTFALoop.h"

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

  Full description of class still missing
*/

/*!
  The signals can be in any order on entry.
  First we sort the subpool by name+receiver coordinates, component, t0.
  We test if sampling rate and t0 are compatible internally for each station (may be different from other stations).
*/
bool HVTFAStationSignals::organizeSubPool(SubSignalPool * subPool)
{
  TRACE;
  // Sorting by name+receiver coordinates, component and t0
  SortKey::clear();
  SortKey::add(MetaDataFactory::Name);
  SortKey::add(MetaDataFactory::ReceiverX);
  SortKey::add(MetaDataFactory::ReceiverY);
  SortKey::add(MetaDataFactory::Component);
  SortKey::add(MetaDataFactory::StartTime);
  subPool->sort();
  // Consistency checks : samplingPeriod and T0 compatibility
  SubSignalPool::iterator itPool=subPool->begin();
  Signal * sig=*itPool;
  QString refName=sig->name();
  Point refRec=sig->receiver();
  double refDt=sig->samplingPeriod();
  DateTime refStartTime=sig->startTime();
  for( ++itPool;itPool!=subPool->end();++itPool) {
    sig=*itPool;
    if(refName!=sig->name() || refRec!=sig->receiver()) {
      refName=sig->name();
      refRec=sig->receiver();
      refDt=sig->samplingPeriod();
      refStartTime=sig->startTime();
    } else {
      if(refDt!=sig->samplingPeriod()) {
        Message::warning(MSG_ID, tr("Creating array"),
                                  tr("The samling rate must be the same for all components." ),
                                  Message::cancel());
        return false;
      }
      double nsamplingPeriod0=fabs(sig->startTime().secondsTo(refStartTime))/refDt;
      if(nsamplingPeriod0-round(nsamplingPeriod0)>0.01*refDt) {
        Message::warning(MSG_ID, tr("Creating array"),
                                  tr("The differences between t0s must be a multiple of "
                                     "sampling period. Problem with signal ID %1." ).arg(sig->id()),
                                   Message::cancel());
        return false;
      }
    }
  }
  return true;
}

void HVTFAStationSignals::writeLog(const QDir& d, const QString log)
{
  TRACE;
  QFile f(d.absoluteFilePath(originalSignals()->name() + ".log"));
  if(!f.open(QIODevice::WriteOnly)) {
    Message::warning(MSG_ID, tr("Saving log file"),
                     tr("Unable to open file %1 for writing").arg(f.fileName()), Message::cancel(), true);
  } else {
    QTextStream s(&f);
    s << log;
  }
}

HVTFALoop * HVTFAStationSignals::createLoop(const TimeRange& tw,  HVTFAParameters * param)
{
  TRACE;
  TimeRange localTw=tw;
  if(localTw.start()<originalSignals()->minTime()) {
    localTw.setStart(originalSignals()->minTime());
  }
  if(localTw.end()>originalSignals()->maxTime()) {
    localTw.setEnd(originalSignals()->maxTime());
  }
  if(localTw.lengthSeconds()<=0.0) {
    App::log(tr("No signal available for station %1 between times %2 and %3\n")
             .arg(originalSignals()->name())
             .arg(tw.start().toString())
             .arg(tw.end().toString()));
    return nullptr;
  }
  HVTFALoop * loop=new HVTFALoop;
  loop->_database=originalSignals()->firstValidSignal()->database(); // Only for user messaging
  loop->_param=param;
  loop->_samplingPeriod=originalSignals()->samplingPeriod();
  loop->_sampFreq=1.0/loop->_samplingPeriod;
  loop->_startTime=localTw.start();
  loop->_fdotmax.setFileName(loop->_param->outputDirectory().absoluteFilePath(originalSignals()->name()+".max"));
  // Compute Fourier transform for all components
  for(int i=0; i<3; i++) {
    copyOriginalSignal(i, localTw);
    DoubleSignal & sig=*processed(i);
    sig.subtractValue();
    sig.fastFourierTransform(DoubleSignal::Spectrum);
  }
  loop->_signals[0]=processed(0);
  loop->_signals[1]=processed(1);
  loop->_signals[2]=processed(2);
  return loop;
}
