/***************************************************************************
**
**  This file is part of geopsy-hv.
**
**  geopsy-hv 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.
**
**  geopsy-hv 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-01-20
**  Copyright: 2020

**
***************************************************************************/

#include <QGpCoreTools.h>
#include <HVCore.h>

#include "geopsy-hvVersion.h"
#include "geopsy-hvInstallPath.h"

PACKAGE_INFO("geopsy-hv", GEOPSY_HV)

ApplicationHelp * help();

enum Mode {HV, Spectrum, HVRotate, SpectrumRotate};
Mode mode=HV;
QStringList timeWindowFiles;

bool postOptions(int& argc, char ** argv, HVParameters * param)
{
  bool rotate=false;
  int i, j = 1;
  for (i=1; i<argc; i++) {
    QByteArray arg = argv[i];
    if (arg[0]=='-') {
      if(arg=="-hv") {
        mode=HV;
      } else if(arg=="-spectrum") {
        mode=Spectrum;
      } else if(arg=="-rotate") {
        rotate=true;
      } else if(arg=="-load-windows") {
        CoreApplication::checkOptionArg(i, argc, argv);
        timeWindowFiles.append(argv[i]);
      } else if(arg=="-param-example") {
        QTextStream(stdout) << param->AbstractParameters::toString()
                            << param->toString();
        ::exit(0);
      } else {
        argv[j++]=argv[i];
      }
    } else {
      argv[j++]=argv[i];
    }
  }
  argc=j;
  if(rotate) {
    switch(mode) {
    case Spectrum:
      mode=SpectrumRotate;
      break;
    default:
      mode=HVRotate;
      break;
    }
  }
  timeWindowFiles=File::expand(timeWindowFiles);
  return true;
}

int main(int argc, char ** argv)
{
  CoreApplication a(argc, argv, help);
  // No plugins are loaded, TODO: pre-parse options to activate plugins
  GeopsyCoreEngine gp(false);
  skipOpenBlasMultiThreading();

  HVParameters * param=new HVParameters;
  CoreToolInterface gti;
  gti.setParameters(param);
  if(!gti.setOptions(argc, argv)) {
    return 2;
  }
  if(!postOptions(argc, argv, param)) {
    return 2;
  }
  if(!CoreApplication::checkRemainingArgs(argc, argv)) {
    return 2;
  }
  QDir outputDir(gti.outputBaseName());
  QList<const AbstractSignalGroup *>::const_iterator it;
  for(it=gti.groups().begin(); it!=gti.groups().end(); it++) {
    AbstractHVTool  * tool=nullptr;
    switch(mode) {
    case HV:
      tool=new HVTool;
      break;
    case Spectrum:
      tool=new SpectrumTool;
      break;
    case HVRotate:
      tool=new HVRotateTool;
      break;
    case SpectrumRotate:
      tool=new SpectrumRotateTool;
      break;
    }
    if(!tool) {
      App::log(tr("Unsupported mode\n"));
      return 2;
    }
    const AbstractSignalGroup * group=*it;
    SubSignalPool subPool=gti.subPool(group);
    if(!tool->setSubPool(&subPool)) {
      App::log(tr("Error initializing group '%1'\n").arg(subPool.name()));
      return 2;
    }
    if(!tool->setParameters(*param)) {
      return 2;
    }
    if(timeWindowFiles.isEmpty()) {
      tool->autoWindows();
    } else {
      if(!tool->loadWindows(timeWindowFiles)) {
        return 2;
      }
    }
    tool->start();
    tool->waitFinished();
    App::log(tr("Saving to '%1'...\n").arg(outputDir.absolutePath()));
    tool->save(outputDir);
    delete tool;
    gp.cache()->free(); // Avoid to keep all signals from all groups in memory
  }
  return 0;
}

ApplicationHelp * help()
{
  TRACE;
  ApplicationHelp * h=new ApplicationHelp;
  h->setOptionSummary( "[OPTIONS]");
  h->setComments("Calculate H/V spectral ratios and spectra for ambient vibrations.");
  h->addGroup("geopsy-hv", "geopsy-hv");
  h->addOption("-hv","HV spectral ratio mode (default).");
  h->addOption("-spectrum","Smooth spectra mode.");
  h->addOption("-rotate","Produce results in all directions, either HV or Spectrum.");
  h->addOption("-load-windows <FILE>", "Load time windows from FILE. Format:\n"
                                       "  ### Time Windows ###\n"
                                       "  # From time      To time\n"
                                       "  YYYYMMddhhmmss.z YYYYMMddhhmmss.z\n"
                                       "  ...\n"
                                       "  ### End Time Windows ###\n"
                                       "Several instance of this option and wildcards are accepted.\n"
                                       "If only one file is provided, the same window set is applied to all stations. Else, "
                                       "file names must match the station names."
                                       "(default: automatic windows).");
  h->addOption("-param-example","Output default parameters, template to build a new parameter file.");
  CoreToolInterface::setHelp(h);
  return h;
}
