/***************************************************************************
**
**  This file is part of gplivemodel.
**
**  gplivemodel 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.
**
**  gplivemodel 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: 2008-11-07
**  Copyright: 2008-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpCoreTools.h>
#include <QGpCoreWave.h>
#include <SciFigs.h>
#include "EllipticityThread.h"
#include "DispersionThread.h"
#include "EllipticityThread.h"

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

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
EllipticityThread::EllipticityThread(QObject * parent)
    : Seismic1DThread(parent)
{
  TRACE;
  _nRayleigh=1;
  _abs=false;
  _angleDeg=false;
  _angleRad=false;
  _oneMode=false;
}

/*!
  Description of constructor still missing
*/
EllipticityThread::EllipticityThread(const EllipticityThread& o)
    : Seismic1DThread(o)
{
  TRACE;
  _nRayleigh=o._nRayleigh;
  _abs=o._abs;
  _angleDeg=o._angleDeg;
  _angleRad=o._angleRad;
  _oneMode=o._oneMode;
}

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

void EllipticityThread::initResultsGraphs(GraphicSheet * sheet)
{
  TRACE;
  CurvesThread::initResultsGraphs(sheet);
  AxisWindow * w=_layer->graph();
  w->xAxis()->setFrequency();
  w->yAxis()->setTitle(tr("Ellitpticity (H/V)"));
  w->yAxis()->setTitleInversedScale(tr("Ellitpticity (V/H)"));
  if(_abs) {
    if(_angleDeg) {
      w->yAxis()->setRange(0, 90.0);
      setAutomaticLimits(false);
    } else if(_angleRad) {
      w->yAxis()->setRange(0, 0.5*M_PI);
      setAutomaticLimits(false);
    } else {
      w->yAxis()->setScaleType(Scale::Log);
      w->yAxis()->setAutoTicks(false);
      w->yAxis()->setMajorTicks(2.0);
      w->yAxis()->setMinorTicks(0.5);
    }
  } else {
    if(_angleDeg) {
      w->yAxis()->setRange(-90.0, 90.0);
      setAutomaticLimits(false);
    } else if(_angleRad) {
      w->yAxis()->setRange(-0.5*M_PI, 0.5*M_PI);
      setAutomaticLimits(false);
    }
  }
}

bool EllipticityThread::setParameters(int& argc, char ** argv)
{
  TRACE;
  int i, j=1;
  for(i=1; i<argc; i++) {
    QByteArray arg=argv[i];
    if(arg[0]=='-') {
      if(arg=="-R") {
        CoreApplication::checkOptionArg(i, argc, argv);
        _nRayleigh=atoi(argv[i]);
      } else if (arg=="-one-mode") {
        _oneMode=true;
      } else if(arg=="-abs") {
        _abs=true;
      } else if(arg=="-angle" || arg=="-angle-deg") {
        _angleDeg=true;
        _angleRad=false;
      } else if(arg=="-angle-rad") {
        _angleRad=true;
        _angleDeg=false;
      } else {
        argv[j++]=argv[i];
      }
    } else {
      argv[j++]=argv[i];
    }
  }
  if(j < argc) {
    argv[j]=nullptr;
    argc=j;
  }
  return CurvesThread::setParameters(argc, argv);
}

void EllipticityThread::run(GeophysicalModel * m)
{
  if(_nRayleigh>0) {
    Rayleigh rayleigh(static_cast<Seismic1DModel *>(m));
    Dispersion dispersion (_nRayleigh, &_x);
    dispersion.setPrecision(1e-10); // Highest precision with double
    Ellipticity ell(_nRayleigh, &_x);
    if(!dispersion.calculate(&rayleigh, &ell, &_terminated)) {
      return;
    }
    if(_abs) {
      ell.abs();
    }
    if(_angleRad) {
      ell.atanRad();
    } else if(_angleDeg) {
      ell.atanDeg();
    }
    for(int i=0;i<_nRayleigh;i++) {
      _curves.append(ell.curve(i));
    }
  }
}
