/***************************************************************************
**
**  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-03-08
**  Copyright: 2008-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QGpGuiMath.h>

#include "ImageScalingPoint.h"

namespace QGpGuiMath {

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

    Full description of class still missing

    TODO: Use QTableView instead of QTableWidget
  */

  /*!
    Description of constructor still missing
  */
  ImageScalingPoint::ImageScalingPoint(QWidget * parent)
      : QWidget(parent, Qt::Window)
  {
    TRACE;
    setAttribute(Qt::WA_DeleteOnClose, true);
    setupUi(this);

    pointTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    pointTable->setSelectionMode(QAbstractItemView::SingleSelection);
    pointTable->setEditTriggers(QAbstractItemView::AllEditTriggers);
  #if(QT_VERSION > QT_VERSION_CHECK(5, 0, 0))
    pointTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
    pointTable->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Stretch);
  #else
    pointTable->horizontalHeader()->setResizeMode(3, QHeaderView::Stretch);
    pointTable->horizontalHeader()->setResizeMode(4, QHeaderView::Stretch);
  #endif
    Settings::columnWidth(pointTable, "ImageScalingPoint");

    Settings::getWidget(this);
  }

  ImageScalingPoint::~ImageScalingPoint()
  {
    TRACE;
    Settings::setColumnWidth(pointTable, "ImageScalingPoint");
    Settings::setWidget(this);
  }

  void ImageScalingPoint::setReferences(const QList<ImageLayer::ReferencePoint>& ref)
  {
    TRACE;
    _references=ref;
    int n=_references.count();
    pointTable->setRowCount(n);
    for(int i=0; i<n; i++) {
      createItem(i);
    }
    setScaling();
  }

  void ImageScalingPoint::add(QPoint p)
  {
    TRACE;
    _references.append(ImageLayer::ReferencePoint());
    ImageLayer::ReferencePoint& pr=_references.last();
    int n=_references.count();
    pr.setName(tr("ref %1").arg(n));
    pr.setImage(p);
    pointTable->setRowCount(n);
    createItem(n-1);
  }

  void ImageScalingPoint::on_applyCancelButton_clicked(QAbstractButton * button)
  {
    TRACE;
    if(applyCancelButton->button(QDialogButtonBox::Apply)==button) {
      emit apply();
    }
  }

  void ImageScalingPoint::on_applyCancelButton_rejected()
  {
    TRACE;
    close();
  }

  void ImageScalingPoint::on_addPoint_clicked()
  {
    TRACE;
    _references.append(ImageLayer::ReferencePoint());
    ImageLayer::ReferencePoint& p=_references.last();
    int n=_references.count();
    p.setName(tr("ref %1").arg(n));
    pointTable->setRowCount(n);
    createItem(n-1);
  }

  void ImageScalingPoint::on_deletePoint_clicked()
  {
    TRACE;
    int row=pointTable->currentRow();
    pointTable->removeRow(row);
    _references.removeAt(row);
    if(row>_references.count()) row--;
    if(row>=0) pointTable->setCurrentCell(row,0);
    setScaling();
  }

  void ImageScalingPoint::on_importCoordinates_clicked()
  {
    TRACE;

    CoordinateFileWidget cr;
    if(cr.read()) {
      QList<NamedPoint> points=cr.points();
      QMap<QString, Point> pointMap;
      for(QList<NamedPoint>::iterator it=points.begin(); it!=points.end(); it++) {
        pointMap.insert(it->name(), *it);
      }
      _utmZone=cr.utmZone();
      int n=_references.count();
      for(int i=0; i<n; i++) {
        QMap<QString, Point>::iterator it=pointMap.find(_references.at(i).name());
        if(it!=pointMap.end()) {
          pointTable->item(i, 3)->setText(QString::number(it->x(), 'f'));
          pointTable->item(i, 4)->setText(QString::number(it->y(), 'f'));
        }
      }
    }
  }

  void ImageScalingPoint::on_exportCoordinates_clicked()
  {
    TRACE;
    int n=_references.count();
    QList<NamedPoint> points;
    for(int i=0; i<n; i++) {
      points.append(NamedPoint(_references.at(i).name(), _references.at(i).real()));
    }
    CoordinateFileWidget::write(points, _utmZone);
  }

  void ImageScalingPoint::on_pointTable_cellChanged (int row, int column)
  {
    TRACE;
    if(row>=0) { // -1 observed when deleting a row
      ImageLayer::ReferencePoint& p=_references[row];
      switch(column) {
      default:
        p.setName(pointTable->item(row,column)->text());
        break;
      case 1:
        p.image().setX(pointTable->item(row,column)->text().toInt());
        break;
      case 2:
        p.image().setY(pointTable->item(row,column)->text().toInt());
        break;
      case 3:
        p.real().setX(pointTable->item(row,column)->text().toDouble());
        break;
      case 4:
        p.real().setY(pointTable->item(row,column)->text().toDouble());
        break;
      }
      setScaling();
    }
  }

  void ImageScalingPoint::setScaling()
  {
    TRACE;
    if(_references.count()>1) {
      Point2D o, s;
      ImageLayer::scaling(_references, o, s);
      QString str=tr("Origin: %1,%2 ; Scale %3,%4")
                  .arg(o.x(), 0, 'f')
                  .arg(o.y(), 0, 'f')
                  .arg(s.x(), 0, 'f')
                  .arg(s.y(), 0, 'f');
      if(fabs((fabs(s.x())-fabs(s.y()))/s.x())>0.1) {
        str+=tr("\nX and Y scales differ: for maps, make sure that Y axis is parallel to north.");
      }
      scale->setText(str);
    } else {
      scale->setText(tr("Not enough point to calculate scale, pick or add new points."));
    }
  }

  void ImageScalingPoint::createItem(int index)
  {
    TRACE;
    const ImageLayer::ReferencePoint& p=_references.at(index);
    QTableWidgetItem * item;
    item=new QTableWidgetItem(p.name());
    pointTable->setItem(index, 0, item);
    item=new QTableWidgetItem(QString::number(p.image().x()));
    pointTable->setItem(index, 1, item);
    item=new QTableWidgetItem(QString::number(p.image().y()));
    pointTable->setItem(index, 2, item);
    item=new QTableWidgetItem(QString::number(p.real().x(), 'f'));
    pointTable->setItem(index, 3, item);
    item=new QTableWidgetItem(QString::number(p.real().y(), 'f'));
    pointTable->setItem(index, 4, item);
  }

} // namespace QGpGuiMath
