/***************************************************************************
**
**  This file is part of waran.
**
**  waran 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.
**
**  waran 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: 2013-04-07
**  Copyright: 2013-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "TapeCoordinateItem.h"

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

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
TapeCoordinateItem::TapeCoordinateItem(QObject *parent)
  : QAbstractTableModel(parent)
{
  TRACE;
}

int TapeCoordinateItem::rowCount(const QModelIndex&) const
{
  TRACE;
  return _points.count();
}

int TapeCoordinateItem::columnCount(const QModelIndex&) const
{
  TRACE;
  return 6;
}

QVariant TapeCoordinateItem::data(const QModelIndex & index, int role) const
{
  TRACE;
  const TapePoint& p=_points.at(index.row());
  switch(role) {
  case Qt::EditRole:
  case Qt::DisplayRole:
    switch(index.column()) {
    case 0:
      return p.name();
    case 1:
      return p.x();
    case 2:
      return p.y();
    case 3:
      return p.typeString();
    case 4:
      return p.stddev().xRadius();
    case 5:
      return p.stddev().yRadius();
    default:
      break;
    }
    break;
  default:
    break;
  }
  return QVariant();
}

bool TapeCoordinateItem::setData(const QModelIndex & index, const QVariant & value, int role)
{
  TRACE;
  if(role!=Qt::EditRole) {
    return false;
  }
  TapePoint& p=_points[index.row()];
  switch(index.column()) {
  case 0:
    return false;
  case 1:
    p.setX(value.toDouble());
    emit pointChanged();
    return true;
  case 2:
    p.setY(value.toDouble());
    emit pointChanged();
    return true;
  case 3:
    p.setType(value.toString());
    emit typeChanged();
    return true;
  default:
    break;
  }
  return false;
}

QVariant TapeCoordinateItem::headerData(int section, Qt::Orientation orientation, int role) const
{
  TRACE;
  if(orientation==Qt::Horizontal && role==Qt::DisplayRole) {
    switch(section) {
    case 0: return tr("Name");
    case 1: return tr("X");
    case 2: return tr("Y");
    case 3: return tr("Type");
    case 4: return tr("dX");
    case 5: return tr("dY");
    default:
      break;
    }
  }
  return QVariant();
}

Qt::ItemFlags TapeCoordinateItem::flags(const QModelIndex& index) const
{
  TRACE;
  switch(index.column()) {
  case 0:
  case 4:
  case 5:
    return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
  default:
    break;
  }
  return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
}

int TapeCoordinateItem::indexOf(const QString& name)const
{
  TRACE;
  for(int i=_points.count()-1; i>=0; i--) {
    if(name==_points.at(i).name()) {
      return i;
    }
  }
  return -1;
}

void TapeCoordinateItem::add(const QString& name)
{
  TRACE;
  beginInsertRows(QModelIndex(), _points.count(), _points.count());
  TapePoint p(name);
  // Automatic identification of point types
  switch(_points.count()) {
  case 0:
    p.setType(TapePoint::Fixed);
    break;
  case 1:
    p.setType(TapePoint::North);
    break;
  case 2:
    p.setType(TapePoint::Eastward);
    break;
  default:
    break;
  }
  _points.append(p);
  endInsertRows();
}

void TapeCoordinateItem::setPoint(const QString& name, const Point2D& p, const QGpCoreMath::Ellipse &stddev)
{
  TRACE;
  int i=indexOf(name);
  if(i>=0) {
    _points[i]=p;
    _points[i].setStddev(stddev);
    emit pointChanged();
  }
}

void TapeCoordinateItem::setPriorCoordinates(int index)
{
  TRACE;
  switch(_points[index].type()) {
  case TapePoint::Fixed:
  case TapePoint::North:
  case TapePoint::Eastward:
    break;
  case TapePoint::Free:
    _points[index].setType(TapePoint::Prior);
    break;
  case TapePoint::Prior:
    _points[index].setType(TapePoint::Free);
    break;
  }
}

bool TapeCoordinateItem::load(const QString& fileName)
{
  QFile f(fileName);
  if(!f.open(QIODevice::ReadOnly)) {
    Message::warning(MSG_ID, tr("Loading coordinates"), tr("Cannot open file %1 for reading").arg(fileName));
    return false;
  }
  QTextStream s(&f);
  while(!s.atEnd()) {
    QString line=s.readLine();
    NamedPoint p;
    if(p.fromString(StringSection(line))) {
      setPoint(p.name(), p, QGpCoreMath::Ellipse());
    }
  }
  return true;
}

bool TapeCoordinateItem::save(const QString& fileName) const
{
  QFile f(fileName);
  if(!f.open(QIODevice::WriteOnly)) {
    Message::warning(MSG_ID, tr("Saving coordinates"), tr("Cannot open file %1 for writing").arg(fileName));
    return false;
  }
  QTextStream s(&f);
  for(QList<TapePoint>::const_iterator it=_points.begin(); it!=_points.end(); it++) {
    s << it->toString(20, 'f') << endl;
  }
  return true;
}
