/***************************************************************************
**
**  This file is part of QGpGuiMath.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2008-09-16
**  Copyright: 2008-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "CoordinateFileWidget.h"

namespace QGpGuiMath {

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

    Full description of class still missing
  */

  /*!
  Description of constructor still missing
  */
  CoordinateFileWidget::CoordinateFileWidget(QWidget *parent)
    : Dialog(parent)
  {
    TRACE;
    setupUi(this);

    coordinateParser->setFileEngine(new CoordinateFile);
    connect(coordinateParser->fileEngine(), SIGNAL(rowsParsed()), this, SLOT(enableConversion()));
    // parser does not run when types are changes, hence the above connection is not sufficient
    connect(coordinateParser, SIGNAL(typeChanged()), this, SLOT(enableConversion()));
    connect(convertWidget, SIGNAL(copyReference()), this, SLOT(copyPointToReference()));
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(beforeLeaving()));

    setWindowTitle(tr("Load coordinates"));
    Settings::getRect(this, "coordinateReader");
    Settings::getWidget(convertWidget, "coordinateReader");
    coordinateParser->restoreParserSettings();
  }

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

  bool CoordinateFileWidget::read(QString fileName, const QString& format)
  {
    TRACE;
    coordinateParser->fileEngine()->setParserFile(format);
    if(!coordinateParser->fileEngine()->setFile(fileName)) {
      return false;
    }
    if(exec()==QDialog::Accepted) {
      convertWidget->saveReference();
      coordinateParser->saveParserSettings();
      Settings::setWidget(convertWidget, "coordinateReader", false);
      Settings::setRect(this, "coordinateReader");
      return true;
    } else {
      return false;
    }
  }

  QString CoordinateFileWidget::fileName() const
  {
    TRACE;
    CoordinateFile * f=fileEngine();
    if(f) {
      return f->fileName();
    } else {
      return QString();
    }
  }

  CoordinateFile * CoordinateFileWidget::fileEngine() const
  {
    TRACE;
    return static_cast<CoordinateFile *>(coordinateParser->fileEngine());
  }

  void CoordinateFileWidget::setPoints()
  {
    TRACE;
    _points=fileEngine()->points();
  }

  void CoordinateFileWidget::beforeLeaving()
  {
    TRACE;
    setPoints();
    _utmZone=UtmZone();
    switch(fileEngine()->coordinateType(true)) {
    case CoordinateFile::Undefined:
      break;
    case CoordinateFile::Geographical:
      convert(convertWidget->projection(), convertWidget->reference());
      break;
    case CoordinateFile::UniversalTransverseMercator:
      _utmZone=fileEngine()->utmZone();
      break;
    case CoordinateFile::Local:
      break;
    }
    accept();
  }

  /*!
    Called every time the parser finishes or column type are touched
  */
  void CoordinateFileWidget::enableConversion()
  {
    TRACE;
    setPoints();
    convertWidget->setUtmZone(CoordinateFile::utmZone(_points));
    convertWidget->setEnabled(fileEngine()->coordinateType(false)==CoordinateFile::Geographical);
  }

  void CoordinateFileWidget::copyPointToReference()
  {
    TRACE;
    QMenu * m=new QMenu;
    setPoints();
    QList<NamedPoint>::iterator it;
    for(it=_points.begin(); it!=_points.end(); ++it) {
      QAction * a=m->addAction(it->name());
      connect(a, SIGNAL(triggered()), this, SLOT(copyReference()));
    }
    convertWidget->popupCopyMenu(m);
  }

  void CoordinateFileWidget::copyReference()
  {
    TRACE;
    QAction * a=qobject_cast<QAction *>(sender());
    QString name=a->text();
    QList<NamedPoint>::iterator it;
    for(it=_points.begin(); it!=_points.end(); ++it) {
      if(it->name()==name) {
        convertWidget->setReference(*it);
        break;
      }
    }
  }

  /*!
    Converts to cartesian with \a reference
  */
  void CoordinateFileWidget::convert(CoordinateConvert::Projection projection, const Point2D& reference)
  {
    TRACE;
    App::log(tr("Converting from Geographical coordinates:\n") );
    if(projection==CoordinateConvert::UniversalTransverseMercator) {
      _utmZone=convertWidget->utmZone();
    } else {
      _utmZone=UtmZone();
    }
    QList<NamedPoint>::iterator it;
    for(it=_points.begin(); it!=_points.end(); ++it) {
      App::log(tr("  %1 ---> ").arg(it->toString(10)));
      switch(projection) {
      case CoordinateConvert::Local:
        it->geographicalToRectangular(reference);
        App::log(it->toString(10)+"\n");
        break;
      case CoordinateConvert::UniversalTransverseMercator:
        it->geographicalToUtm(_utmZone);
        App::log(_utmZone.toString()+" "+it->toString(10)+"\n");
        break;
      }
    }
  }

  bool CoordinateFileWidget::write(const QList<NamedPoint>& points, const UtmZone& utmZone, QString fileName)
  {
    TRACE;
    if(fileName.isEmpty()) {
      fileName=Message::getSaveFileName(tr("Save coordinates"), CoordinateFile::allFileFilter());
      if(fileName.isEmpty()) {
        return false;
      }
    }
    NamedPoint reference;
    NamedPoint * referencePtr=0;
    if(!utmZone.isValid() && (fileName.endsWith(".kml") || fileName.endsWith(".geo") || fileName.endsWith(".utm"))) {
      Dialog * d=new Dialog;
      GeographicalReference * dg=new GeographicalReference;
      d->setMainWidget(dg);
      d->setWindowTitle("Geographical coordinate export");
      Settings::getWidget(dg, d->windowTitle());
      Settings::getRect(d, d->windowTitle());
      if(d->exec()==QDialog::Accepted) {
        Settings::setWidget(dg, d->windowTitle());
        Settings::setRect(d, d->windowTitle());
        dg->save();
        reference=dg->reference();
        referencePtr=&reference;
        delete d;
      } else {
        delete d;
        return false;
      }
    }
    return CoordinateFile::write(points, utmZone, referencePtr, fileName);
  }

} // namespace QGpGuiMath
