/***************************************************************************
**
**  This file is part of geopsyrefra.
**
**  geopsyrefra 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.
**
**  geopsyrefra 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: 2004-09-02
**  Copyright: 2004-2019
**    Marc Wathelet
**    Marc Wathelet (ULg, Liège, Belgium)
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QtGui>
#include <GeopsyCore.h>
#include <QGpGuiTools.h>
#include "ToolRefra.h"
#include "ToolRefrad.h"
#include "qtbtoolrefraint.h"
//#include "qtbrefrareport.h"
//#include "qtbhodochronedata.h"

ToolRefra::ToolRefra(QWidget * parent) :
  AbstractToolWidget(parent, 0)
{
  TRACE;
  setWindowIcon(QIcon(":refra-22x22.png"));
  QVBoxLayout * baseLayout=new QVBoxLayout(this);
  _d=new ToolRefrad(this);
  baseLayout->addWidget(_d);
  setWindowTitle(tr("Refraction NA toolbox"));
  setObjectName("ToolRefra");

  connect(_d->startBut,SIGNAL(clicked()), this,SLOT(startInversion()));
  _distSigMaps=nullptr;
}

ToolRefra::~ToolRefra()
{
  TRACE;
  delete [] _distSigMaps;
}

void ToolRefra::updateAllFields()
{
  TRACE;
}

bool ToolRefra::initStations(SubSignalPool * subPool)
{
  TRACE;
  // No test are performed on station names or component, all is accepted
  // Azimuth interval that define the negative abcsissae
  double azimuth=0 /*subPool->azimuth()*/;
  double azimuthMin=azimuth+0.5*M_PI; // between 0 and pi
  double azimuthMax=azimuthMin+M_PI; // between pi and 2*pi
  Curve<Point> srcList=subPool->sources();
  srcList.unique();
  int nSrc=srcList.count();
  // Azimuth is sorting the subpool by source and receiver
  SubSignalPool::iterator it=subPool->begin();
  // List of all distances % at first source taken as reference
  Point pRef=srcList.first();
  for(int iSrc=0;iSrc<nSrc;iSrc++) {
    const Point& psrc=srcList.at(iSrc);
    double az=pRef.azimuthTo(psrc);
    if(az>azimuthMin && az<azimuthMax)
      _distances.push_back(-pRef.distanceTo(psrc));
    else
      _distances.push_back(pRef.distanceTo(psrc));
    double srcAbsc=_distances.back();
    for(;it!=subPool->end() && (*it)->source()==psrc;++it) {
      Signal * sig=*it;
      /*az=sig->sourceReceiverAzimuth();
      if(az>azimuthMin && az<azimuthMax)
        _distances.push_back(srcAbsc-sig->sourceReceiverDistance());
      else
        _distances.push_back(srcAbsc+sig->sourceReceiverDistance());
        */
    }
  }
  // Set number of available picks
  _d->setPickCount(subPool->maximumTimePickCount());
  // Adjust distances arround zero
  double mean=0;
  for(QList<double>::iterator it=_distances.begin();it!=_distances.end();++it) {
    mean+=*it;
  }
  mean/=_distances.count();
  for(QList<double>::iterator it=_distances.begin();it!=_distances.end();++it) {
    *it-=mean;
  }
  // Map sources and rec to sig
  _distSigMaps=new QMap<double, Signal *>[nSrc];
  int iNode=0;
  it=subPool->begin();
  for(int iSrc=0;iSrc<nSrc;iSrc++) {
    const Point& psrc=srcList.at(iSrc);
    _srcDist.push_back(_distances[iNode]);
    iNode++;
    for(;it!=subPool->end() && (*it)->source()==psrc;++it, iNode++) {
      _distSigMaps[iSrc].insert(_distances[iNode],*it);
    }
  }
  // Remove duplicates
  std::sort(_distances.begin(), _distances.end());
  unique(_distances);
  _d->infoLabel->setText(_d->infoLabel->text().arg(azimuth).
                         arg(_distances.count()).arg(nSrc));
  return true;
}

void ToolRefra::startInversion()
{
  TRACE;
  if(_d->outputFile->text().isEmpty()) {
    _d->on_outputFileBrowse_clicked();
    if(_d->outputFile->text().isEmpty()) return;
  }
  int pick=_d->averagePick->currentIndex();
  int dpick=_d->stddevPick->currentIndex()-1;
  int nNodes=_distances.count();
  QString fileName=_d->outputFile->text();
  QFileInfo fi(fileName);
  if(fi.suffix()=="dvt") { // next generation inversion tools
//    RefractionSurvey * hodo=new RefractionSurvey;
//    hodo->setNSrc(_nSrc);
//    
//    delete hodo;
  }
  else {// old generation inversion tools (na_viewer)
    /*HodoChroneData * hodo=
        new HodoChroneData (_srcDist.count(), _distList.count());
    // Set omegas to distList values
    int iNode=0;
    for(double * dist=_distList.first();dist;dist=_distList.next(),iNode++) {
      hodo->setFrequency(iNode,*dist);
      //printf("%i %lg\n",iNode,*dist);
    }
    // Set measurement  times
    int nSrc=_srcDist.count();
    for(int iSrc=0;iSrc<nSrc;iSrc++) {
      double srcNode=_srcDist[iSrc];
      //printf("Src distance %i %lg\n",iSrc, srcNode);
      for(int iRec=0;iRec<nNodes;iRec++) {
        //printf("Rec distance %i %lg\n",iRec, hodo->omega(iRec));
        if(srcNode==hodo->omega(iRec)) {
          //printf("Time src\n");
          hodo->setMean(iRec,iSrc,0.0);
          hodo->setStddev(iRec,iSrc,0.0);
        }
        else if(_distSigMaps[iSrc].contains(hodo->omega(iRec))) {
          Signal * sig=_distSigMaps[iSrc][hodo->omega(iRec)];
          if(sig->time(pick)>=0.0) {
            hodo->setMean(iRec,iSrc,sig->time(pick));
            if(dpick>=0)
              hodo->setStddev(iRec,iSrc,fabs(sig->time(dpick)-sig->time(pick)));
            else hodo->setStddev(iRec,iSrc,0.0);
          }
          else {
            hodo->setMean(iRec,iSrc,HODOCHRONE_INVALID_VALUE);
            hodo->setStddev(iRec,iSrc,0.0);                  
          }
        }
        else {
          hodo->setMean(iRec,iSrc,HODOCHRONE_INVALID_VALUE);
          hodo->setStddev(iRec,iSrc,0.0);        
        }
      }
    }
    RefraReport * report=new RefraReport(true,fileName,0,1);
    report->addParameter(InversionReport::Vs,0);
    report->addParameter(InversionReport::Vp,0);
    report->addOmegas(hodo);
    report->addRefraGoal(hodo);
    delete report;
    
    QStringList argProcess;
    argProcess.push_back("na_viewer");
    argProcess.push_back("-g");
    argProcess.push_back(fileName);
    QProcess process(argProcess);
    process.start();

    delete hodo;*/
  }
}
