/***************************************************************************
**
**  This file is part of gpfksimulator.
**
**  gpfksimulator 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.
**
**  gpfksimulator 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: 2011-01-06
**  Copyright: 2011-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "SourceDelegate.h"

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

  Full description of class still missing
*/

SourceDelegate::SourceDelegate(QObject *parent)
    : QItemDelegate(parent)
{
  TRACE;
  _waveModel=SourceParameters::PlaneWaves;
}

SourceDelegate::~SourceDelegate()
{
  TRACE;
}

QWidget *SourceDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & style,
                                      const QModelIndex &index) const
{
  DoubleSpinBox * sb;
  QComboBox * cb;
  switch(_waveModel) {
  case SourceParameters::PlaneWaves:
    switch (index.column()) {
    case 1:
      cb=new QComboBox(parent);
      cb->addItem(Mode::userPolarization(Mode::Vertical));
      cb->addItem(Mode::userPolarization(Mode::Radial));
      cb->addItem(Mode::userPolarization(Mode::Transverse));
      cb->addItem(Mode::userPolarization(Mode::Rayleigh));
      connect(cb,SIGNAL(currentIndexChanged(int)), this, SLOT(commitWidget()));
      return cb;
    case 2:
    case 4:
      sb=new DoubleSpinBox(parent);
      sb->setWrapping(true);
      sb->setSuffix(" °");
      connect(sb,SIGNAL(valueChanged(double)), this, SLOT(commitWidget()));
      sb->setMinimum(0.0);
      sb->setMaximum(360.0);
      sb->setSingleStep(10.0);
      return sb;
    case 3:
    case 5:
      sb=new DoubleSpinBox(parent);
      connect(sb,SIGNAL(valueChanged(double)), this, SLOT(commitWidget()));
      sb->setMinimum(0.0);
      sb->setMaximum(std::numeric_limits<double>::infinity());
      return sb;
    case 6:
      sb=new DoubleSpinBox(parent);
      connect(sb,SIGNAL(valueChanged(double)), this, SLOT(commitWidget()));
      sb->setMinimum(-std::numeric_limits<double>::infinity());
      sb->setMaximum(std::numeric_limits<double>::infinity());
      sb->setSingleStep(0.1);
      return sb;
    case 7:
      return QItemDelegate::createEditor(parent, style, index);
    case 0:
    default:
      break;
    }
    break;
  case SourceParameters::CircularWaves:
    switch (index.column()) {
    case 1:
      cb=new QComboBox(parent);
      cb->addItem(Mode::userPolarization(Mode::Vertical));
      cb->addItem(Mode::userPolarization(Mode::Radial));
      cb->addItem(Mode::userPolarization(Mode::Transverse));
      cb->addItem(Mode::userPolarization(Mode::Rayleigh));
      return cb;
    case 2:
    case 7:
      sb=new DoubleSpinBox(parent);
      sb->setWrapping(true);
      sb->setSuffix(" °");
      connect(sb,SIGNAL(valueChanged(double)), this, SLOT(commitWidget()));
      sb->setMinimum(0.0);
      sb->setMaximum(360.0);
      return sb;
    case 3:
    case 6:
    case 8:
      sb=new DoubleSpinBox(parent);
      connect(sb,SIGNAL(valueChanged(double)), this, SLOT(commitWidget()));
      sb->setMinimum(0.0);
      sb->setMaximum(std::numeric_limits<double>::infinity());
      return sb;
    case 10:
      return QItemDelegate::createEditor(parent, style, index);
    case 4:
    case 5:
    case 9:
      sb=new DoubleSpinBox(parent);
      connect(sb,SIGNAL(valueChanged(double)), this, SLOT(commitWidget()));
      sb->setMinimum(-std::numeric_limits<double>::infinity());
      sb->setMaximum(std::numeric_limits<double>::infinity());
      sb->setSingleStep(0.1);
      return sb;
    case 0:
    default:
      break;
    }
    break;
  }
  return new QLineEdit(parent);
}

void SourceDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  TRACE;
  DoubleSpinBox * sb;
  QLineEdit * le;
  QComboBox * cb;
  switch(_waveModel) {
  case SourceParameters::PlaneWaves:
    switch (index.column()) {
    case 1: {
        cb=qobject_cast<QComboBox *>(editor);
        if(!cb) return;
        int pos=cb->findText(index.model()->data(index).toString(), Qt::MatchExactly);
        cb->setCurrentIndex(pos);
      }
      break;
    case 2:
    case 4:
    case 3:
    case 5:
    case 6:
      sb=qobject_cast<DoubleSpinBox *>(editor);
      if(!sb) return;
      sb->setValue(index.model()->data(index).toDouble());
      break;
    case 7:
      QItemDelegate::setEditorData(editor, index);
      break;
    case 0:
    default:
      le=qobject_cast<QLineEdit *>(editor);
      if(!le) return;
      le->setText(index.model()->data(index).toString());
      le->selectAll();
      break;
    }
    break;
  case SourceParameters::CircularWaves:
    switch (index.column()) {
    case 1: {
        cb=qobject_cast<QComboBox *>(editor);
        if(!cb) return;
        int pos=cb->findText(index.model()->data(index).toString(), Qt::MatchExactly);
        cb->setCurrentIndex(pos);
      }
      break;
    case 2:
    case 7:
    case 3:
    case 6:
    case 8:
    case 9:
    case 4:
    case 5:
      sb=qobject_cast<DoubleSpinBox *>(editor);
      if( !sb) return;
      sb->setValue(index.model() ->data(index).toDouble());
      break;
    case 10:
      QItemDelegate::setEditorData(editor, index);
      break;
    case 0:
    default:
      le=qobject_cast<QLineEdit *>(editor);
      if( !le) return;
      le->setText(index.model() ->data(index).toString());
      le->selectAll();
      break;
    }
    break;
  }
}

void SourceDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                  const QModelIndex &index) const
{
  TRACE;
  DoubleSpinBox * sb;
  QLineEdit * le;
  QComboBox * cb;
  switch(_waveModel) {
  case SourceParameters::PlaneWaves:
    switch (index.column()) {
    case 1: {
        cb=qobject_cast<QComboBox *>(editor);
        if(!cb) return;
        model->setData(index, cb->currentText());
      }
      break;
    case 2:
    case 4:
    case 3:
    case 5:
    case 6:
      sb=qobject_cast<DoubleSpinBox *>(editor);
      if(!sb) return ;
      model->setData(index, sb->value());
      break;
    case 7:
      break;
    case 0:
    default:
      le=qobject_cast<QLineEdit *>(editor);
      if( !le) return;
      model->setData(index, le->text());
      break;
    }
    break;
  case SourceParameters::CircularWaves:
    switch (index.column()) {
    case 1: {
        cb=qobject_cast<QComboBox *>(editor);
        if(!cb) return;
        model->setData(index, cb->currentText());
      }
      break;
    case 2:
    case 7:
    case 3:
    case 6:
    case 8:
    case 9:
    case 4:
    case 5:
      sb=qobject_cast<DoubleSpinBox *>(editor);
      if( !sb) return ;
      model->setData(index, sb->value());
      break;
    case 10:
      break;
    case 0:
    default:
      le=qobject_cast<QLineEdit *>(editor);
      if( !le) return;
      model->setData(index, le->text());
      break;
    }
    break;
  }
}

QSize SourceDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
{
  TRACE;
  switch(_waveModel) {
  case SourceParameters::PlaneWaves:
    switch (index.column()) {
    case 7:
      return QSize(30, 0);
    default:
      break;
    }
    break;
  case SourceParameters::CircularWaves:
    switch (index.column()) {
    case 10:
      return QSize(30, 0);
    default:
      break;
    }
    break;
  }
  return QItemDelegate::sizeHint(option, index);
}

void SourceDelegate::paint (QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
  TRACE;
  if((index.column()==7 && _waveModel==SourceParameters::PlaneWaves) ||
     (index.column()==10 && _waveModel==SourceParameters::CircularWaves)) {
    QPoint p=option.rect.center();
    drawBackground(painter, option, index);
    QColor c=index.model() ->data(index).value<QColor>();
    painter->fillRect(p.x()-8, p.y()-8, 16, 16 , c);
  } else {
    QItemDelegate::paint(painter, option, index);
  }
}

void SourceDelegate::colorClicked(const QModelIndex& index)
{
  TRACE;
  if((index.column()==7 && _waveModel==SourceParameters::PlaneWaves) ||
     (index.column()==10 && _waveModel==SourceParameters::CircularWaves)) {
    QColor c=index.model()->data(index).value<QColor>();
    c=QColorDialog::getColor(c, Application::activeWindow());
    if(c.isValid()) {
      const_cast<QAbstractItemModel *>(index.model())->setData(index, c);
    }
  }
}
