/***************************************************************************
**
**  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: 2010-06-15
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpGuiWave.h>

#include "MagnetoTelluricThread.h"

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

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
MagnetoTelluricThread::MagnetoTelluricThread(QObject * parent)
    : CurvesThread(parent)
{
  TRACE;
  _res=0;
  _leg=0;
  _appRes=0;
  _phase=0;
}

/*!
  Description of constructor still missing
*/
MagnetoTelluricThread::MagnetoTelluricThread(const MagnetoTelluricThread& o)
    : CurvesThread(o)
{
  TRACE;
  _res=0;
  _leg=0;
  _appRes=0;
  _phase=0;
}

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

bool MagnetoTelluricThread::setParameters(int& argc, char ** argv)
{
  TRACE;
  return CurvesThread::setParameters(argc, argv);
}

void MagnetoTelluricThread::initModelGraphs(GraphicSheet * sheet)
{
  TRACE;
  AxisWindow * w;

  w=new AxisWindow;
  w->setGeometry(sheet->printRight(), 0.5, 6.0, 8.0);
  w->yAxis()->setReversedScale(true);
  w->yAxis()->setTitle(tr("Depth (m)"));
  w->xAxis()->setScaleType(Scale::Log);
  w->xAxis()->setTitle(tr("Resistivity (ohm m)"));
  _res=new LineLayer(w);
  _res->setObjectName("background Res");
  _res->setReferenceLine(new PlotLine2D);
  sheet->addObject(w);
  sheet->showObject(w);

  _leg=createLegend(sheet, sheet->printRight(), 0.5, tr("Background models"));
  connect(_leg, SIGNAL(changed( Legend) ), _res, SLOT(setLegend( Legend) ));
}

void MagnetoTelluricThread::initModelGraphs(const ResultsThread& o)
{
  TRACE;
  const MagnetoTelluricThread& om=static_cast<const MagnetoTelluricThread&>(o);
  AxisWindow * w;

  w=om._res->graph();
  _res=new LineLayer(w);
  _res->setObjectName("foreground Res");
  _res->setReferenceLine(new PlotLine2D);
  _res->addLine(Pen(), Symbol());

  _leg=createLegend(w->sheet(), w->sheet()->printRight(), 0.5, tr("Foreground models"));
  connect(_leg, SIGNAL(changed( Legend) ), _res, SLOT(setLegend( Legend) ));
}

void MagnetoTelluricThread::initResultsGraphs(GraphicSheet * sheet)
{
  TRACE;
  AxisWindow * w;

  w=new AxisWindow;
  w->setGeometry(sheet->printRight(), 0.5, 7.0, 8.0);
  w->xAxis()->setFrequency();
  w->yAxis()->setTitle(tr("Apparent resistivity (ohm m)"));
  w->yAxis()->setTitleInversedScale(tr("Apparent conductivity (S/m)"));
  w->xAxis()->setUnitFactor(0.001);
  w->xAxis()->setTitle(tr("Frequency (kHz)"));
  w->xAxis()->setReversedScale(true);

  sheet->addObject(w);
  sheet->showObject(w);
  sheet->autoResizeContent();

  _appRes=new LineLayer(w);
  _appRes->setObjectName(objectName()+" app. res.");
  _appRes->setReferenceLine(new MagnetoTelluricLine);
  _appRes->setPointOptions(new MagnetoTelluricPointOptions(MagnetoTelluricPointOptions::ApparentResistivity));
  QObject::connect(legend(), SIGNAL(changed( Legend) ), _appRes, SLOT(setLegend( Legend) ));

  w=new AxisWindow;
  w->setGeometry(sheet->printRight(), 0.5, 7.0, 8.0);
  w->xAxis()->setFrequency();
  w->yAxis()->setTitle(tr("ase (degrees)"));
  w->xAxis()->setUnitFactor(0.001);
  w->xAxis()->setTitle(tr("Frequency (kHz)"));
  w->xAxis()->setReversedScale(true);

  sheet->addObject(w);
  sheet->showObject(w);
  sheet->autoResizeContent();

  _phase=new LineLayer(w);
  _phase->setObjectName(objectName()+" phase");
  _phase->setReferenceLine(new MagnetoTelluricLine);
  _phase->setPointOptions(new MagnetoTelluricPointOptions(MagnetoTelluricPointOptions::PhaseDegrees));
  QObject::connect(legend(), SIGNAL(changed( Legend) ), _phase, SLOT(setLegend( Legend) ));
}

void MagnetoTelluricThread::initResultsGraphs(const ResultsThread& o)
{
  TRACE;
  const MagnetoTelluricThread& om=static_cast<const MagnetoTelluricThread&>(o);
  _appRes=new LineLayer(om._appRes->graph());
  _appRes->setObjectName(objectName()+" app. res.");
  _appRes->setReferenceLine(new MagnetoTelluricLine);
  _appRes->setPointOptions(new MagnetoTelluricPointOptions(MagnetoTelluricPointOptions::ApparentResistivity));
  connect(legend(), SIGNAL(changed( Legend) ), _appRes, SLOT(setLegend( Legend) ));

  _phase=new LineLayer(om._phase->graph());
  _phase->setObjectName(objectName()+" phase");
  _phase->setReferenceLine(new MagnetoTelluricLine);
  _phase->setPointOptions(new MagnetoTelluricPointOptions(MagnetoTelluricPointOptions::PhaseDegrees));
  QObject::connect(legend(), SIGNAL(changed( Legend) ), _phase, SLOT(setLegend( Legend) ));
}

void MagnetoTelluricThread::addModel(GeophysicalModel * m)
{
  TRACE;
  Resistivity1DModel * mr=static_cast<Resistivity1DModel *>(m);
  int i;
  const Legend& leg=_leg->legend();
  PlotLine2D * line;
  i=_res->count();
  line=static_cast<PlotLine2D *>(_res->addLine(leg.pen(i), leg.symbol(i)) );
  line->curve()=mr->profile().curve();
}

void MagnetoTelluricThread::setModel(GeophysicalModel * m)
{
  TRACE;
  Resistivity1DModel * mr=static_cast<Resistivity1DModel *>(m);
  static_cast<PlotLine2D *>(_res->line(0) )->curve()=mr->profile().curve();
}

void MagnetoTelluricThread::showCurves()
{
  TRACE;
  if(isRunning()) return;
  _appRes->clear();
  _phase->clear();
  MagnetoTelluricLine * line;
  const Legend& leg=legend()->legend();
  int n=_curves.count();
  for(int i=0;i<n; i++) {
    line=static_cast<MagnetoTelluricLine *>(_appRes->addLine(leg.pen(i), leg.symbol(i)) );
    line->curve()=_curves.at(i);
    line=static_cast<MagnetoTelluricLine *>(_phase->addLine(leg.pen(i), leg.symbol(i)) );
    line->curve()=_curves.at(i);
  }
  if(automaticLimits()) setResultsLimits();
  _appRes->graph()->deepUpdate();
  _phase->graph()->deepUpdate();
}

void MagnetoTelluricThread::clear()
{
  TRACE;
  _res->clear();
  _appRes->clear();
  _phase->clear();
  resultsDeepUpdate();
}

void MagnetoTelluricThread::modelDeepUpdate()
{
  TRACE;
  _res->graph()->deepUpdate();
}

void MagnetoTelluricThread::resultsDeepUpdate()
{
  TRACE;
  _appRes->graph()->deepUpdate();
  _phase->graph()->deepUpdate();
}

void MagnetoTelluricThread::setModelLimits()
{
  TRACE;
  Rect r=_res->graphContent()->boundingRect();
  _res->graph()->xAxis()->setRange(r.x1()*0.9, r.x2()*1.1);
  _res->graph()->yAxis()->setRange(0.0, r.y2()*1.1);
}

void MagnetoTelluricThread::setResultsLimits()
{
  TRACE;
  Rect r;
  r=_appRes->boundingRect();
  if(!r.isNull()) {
    _appRes->graph()->xAxis()->setRange(r.x1(), r.x2());
    _appRes->graph()->yAxis()->setRange(r.y1()*0.9, r.y2()*1.1);
  }
  r=_phase->boundingRect();
  if(!r.isNull()) {
    _phase->graph()->xAxis()->setRange(r.x1(), r.x2());
    _phase->graph()->yAxis()->setRange(r.y1()*0.9, r.y2()*1.1);
  }
}

void MagnetoTelluricThread::run()
{
  TRACE;
  _curves.clear();
  QList<GeophysicalModel *>::iterator it;
  for(it=_models.begin(); it!=_models.end(); it++) {
    if(terminated()) break;
    run(*it);
  }
  qDeleteAll(_models);
}

void MagnetoTelluricThread::run(GeophysicalModel * m)
{
  TRACE;
  Resistivity1DModel * mr=static_cast<Resistivity1DModel *>(m);
  MagnetoTelluricFactory fac;
  fac.setX(_x);
  fac.calculate(*mr);
  _curves.append(fac.curve());
}
