/***************************************************************************
**
**  This file is part of geopsy.
**
**  geopsy 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.
**
**  geopsy 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: 2005-09-20
**  Copyright: 2005-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include <QSpinBox>
#include <QLineEdit>
#include <QItemDelegate>
#include <QHeaderView>
#include <QComboBox>

#include "ViewParamEditor.h"

ViewParamDelegate::ViewParamDelegate(QObject *parent)
    : QItemDelegate(parent)
{
  TRACE;
  _tableFieldList=MetaDataFactory::instance()->registeredNames();
}

QWidget *ViewParamDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & ,
                                         const QModelIndex &index) const
{
  switch(index.column()) {
  case 0: {
      QComboBox *w=new QComboBox (parent);
      w->addItems(_tableFieldList);
      connect(w, SIGNAL(activated(int)), this, SLOT(commit()));
      return w;
    }
  case 1: {
      QComboBox * w=new QComboBox(parent);
      QModelIndex metaDataNameIndex=static_cast<const QAbstractTableModel *>(index.model())->index(index.row(), 0, index.parent());
      MetaDataIndex dataIndex=MetaDataFactory::instance()->index(index.model()->data(metaDataNameIndex).toString());
      MetaData * d=MetaDataFactory::instance()->create(dataIndex.id());
      ASSERT(d);
      w->addItems(d->indexList(dataIndex.subId()));
      delete d;
      w->setEditable(true);
      connect(w, SIGNAL(editTextChanged(QString)), this, SLOT(commit()));
      return w;
    }
  default:
    QLineEdit * w=new QLineEdit(parent);
    return w;
  }
}

void ViewParamDelegate::commit()
{
  TRACE;
  QWidget * w=qobject_cast<QWidget *>(sender());
  if(w) {
    emit commitData(w);
  }
}

void ViewParamDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  TRACE;
  switch(index.column()) {
  case 0: {
      QComboBox *w=qobject_cast<QComboBox *>(editor);
      if(!w) return;
      int pos=w->findText(index.model()->data(index).toString(), Qt::MatchExactly);
      w->setCurrentIndex(pos);
      break;
    }
  case 1: {
      QComboBox * w=qobject_cast<QComboBox *>(editor);
      if(!w) return;
      w->setEditText(index.model()->data(index).toString());
      break;
    }
  default:
    QLineEdit * w=qobject_cast<QLineEdit *>(editor);
    if( !w) return;
    w->setText(index.model() ->data(index).toString());
    w->selectAll();
    break;
  }
}

void ViewParamDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
                                        const QModelIndex &index) const
{
  TRACE;
  switch(index.column()) {
  case 0: {
      QComboBox *w=qobject_cast<QComboBox *>(editor);
      if(!w) return;
      model->setData(index, w->currentText());
      break;
    }
  case 1: {
      QComboBox * w=qobject_cast<QComboBox *>(editor);
      if(!w) return;
      model->setData(index, w->currentText());
      break;
    }
  default:
    QLineEdit * w=qobject_cast<QLineEdit *>(editor);
    if( !w) return;
    model->setData(index, w->text());
    break;
  }
}

/*
 *  Constructs a ViewParamEditor as a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'.
 */
ViewParamEditor::ViewParamEditor(QWidget *parent, Qt::WindowFlags f)
    : QWidget(parent, f)
{
  TRACE;
  setupUi(this);

  selFieldList->setColumnCount(3);
  QStringList hLabels;
  hLabels << tr("Data field")<< tr("Index") << tr("Title");
  selFieldList->setHorizontalHeaderLabels (hLabels);
  selFieldList->setSelectionBehavior(QAbstractItemView::SelectItems);
  selFieldList->setSelectionMode(QAbstractItemView::SingleSelection);
  selFieldList->setEditTriggers(QAbstractItemView::AllEditTriggers);
  selFieldList->setItemDelegate (new ViewParamDelegate(this));
#if(QT_VERSION > QT_VERSION_CHECK(5, 0, 0))
  selFieldList->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
#else
  selFieldList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
#endif
}

void ViewParamEditor::setIndexState(QTableWidgetItem * item, const MetaDataIndex& index)
{
  TRACE;
  if(index.id()<MetaDataFactory::DataCount) { // No index for standard meta data
    item->setFlags(nullptr);
  } else {
    MetaData * d=MetaDataFactory::instance()->create(index.id());
    ASSERT(d);
    if(d->hasIndex(index.subId())) {
      item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
    } else {
      item->setFlags(nullptr);
    }
    delete d;
  }
}

void ViewParamEditor::on_addTableField_clicked()
{
  TRACE;
  int n=selFieldList->rowCount();

  QString name, index, title;
  MetaDataIndex dataIndex;
  if(n>0) {
    name=selFieldList->item(n-1,0)->text();
    index=selFieldList->item(n-1,1)->text();
    title=selFieldList->item(n-1,2)->text();
    dataIndex=MetaDataFactory::instance()->index(name);
  } else {
    name=MetaDataFactory::instance()->baseName(MetaDataFactory::Name);
    index="0";
    title=MetaDataFactory::instance()->title(MetaDataFactory::Name);
    dataIndex=MetaDataFactory::Name;
  }
  selFieldList->setRowCount(n + 1);
  QTableWidgetItem *newItem;

  selFieldList->blockSignals(true);
  newItem=new QTableWidgetItem(name);
  selFieldList->setItem(n,0, newItem);
  newItem=new QTableWidgetItem(index);
  selFieldList->setItem(n,1, newItem);
  setIndexState (newItem, dataIndex);
  newItem=new QTableWidgetItem(title);
  selFieldList->setItem(n,2, newItem);
  selFieldList->blockSignals(false);

  selFieldList->resizeRowToContents(n);
  selFieldList->setCurrentItem(selFieldList->item(n, 0));
  selFieldList->scrollToItem(selFieldList->item(n, 0));
}

void ViewParamEditor::on_removeTableField_clicked()
{
  TRACE;
  int n=selFieldList->currentRow();
  selFieldList->removeRow(n);
  if(n >= selFieldList->rowCount()) n=selFieldList->rowCount() - 1;
  selFieldList->setCurrentItem(selFieldList->item(n, 0));
}

void ViewParamEditor::on_insertTableField_clicked()
{
  TRACE;
  int n=selFieldList->currentRow();

  if(n>=0) {
    QString name=selFieldList->item(n,0)->text();
    QString index=selFieldList->item(n,1)->text();
    QString title=selFieldList->item(n,2)->text();
    MetaDataIndex dataIndex=MetaDataFactory::instance()->index(name);
    selFieldList->insertRow(n);
    QTableWidgetItem *newItem;

    selFieldList->blockSignals(true);
    newItem=new QTableWidgetItem(name);
    selFieldList->setItem(n,0, newItem);
    newItem=new QTableWidgetItem(index);
    setIndexState (newItem, dataIndex);
    selFieldList->setItem(n,1, newItem);
    newItem=new QTableWidgetItem(title);
    selFieldList->setItem(n,2, newItem);
    selFieldList->blockSignals(false);

    selFieldList->setCurrentItem(selFieldList->item(n, 0));
    selFieldList->resizeRowToContents(n);
  } else {
    on_addTableField_clicked();
  }
}

void ViewParamEditor::initTableFields(const MetaDataFieldList& sel)
{
  TRACE;
  selFieldList->blockSignals(true);
  selFieldList->setRowCount(sel.count());
  QTableWidgetItem *newItem;
  int n=selFieldList->rowCount();
  for(int i=0;i<n;i++) {
    const MetaDataField& field=sel.at(i);
    newItem=new QTableWidgetItem(MetaDataFactory::instance()->baseName(field));
    selFieldList->setItem(i,0, newItem);
    newItem=new QTableWidgetItem(field.index());
    setIndexState(newItem, field);
    selFieldList->setItem(i,1, newItem);
    newItem=new QTableWidgetItem(field.title());
    selFieldList->setItem(i,2, newItem);
    selFieldList->resizeRowToContents(i);
  }
  selFieldList->blockSignals(false);
  selFieldList->resizeColumnToContents(1);
  selFieldList->resizeColumnToContents(2);
}

void ViewParamEditor::getTableFields(MetaDataFieldList& sel)
{
  TRACE;
  MetaDataField field;
  sel.clear();
  int n=selFieldList->rowCount();
  for(int i=0;i < n;i++ ) {
    field=MetaDataFactory::instance()->index(selFieldList->item(i, 0)->text());
    field.setIndex(selFieldList->item(i, 1)->text());
    field.setTitle(selFieldList->item(i, 2)->text());
    sel.add(field);
  }
}

void ViewParamEditor::on_selFieldList_itemChanged(QTableWidgetItem * item)
{
  TRACE;
  if(!item) return;
  int row=selFieldList->row(item);
  int column=selFieldList->column(item);
  if(column<=1) {
    QTableWidgetItem * itemId=selFieldList->item(row, 0);
    QTableWidgetItem * itemIndex=selFieldList->item(row, 1);
    QTableWidgetItem * itemTitle=selFieldList->item(row, 2);

    MetaDataIndex index=MetaDataFactory::instance()->index(itemId->text());
    index.setIndex(itemIndex->text());
    if(column==0) {
      setIndexState(itemIndex, index);
    }
    itemTitle->setText(MetaDataFactory::instance()->title(index));
  }
  fieldTemplate->setCurrentIndex(2);
}

void ViewParamEditor::on_fieldTemplate_currentIndexChanged(int index)
{
  TRACE;
  if(index==0) {
    MetaDataFieldList sel;
    sel.setDefaults();
    initTableFields(sel);
  } else if(index==1) {
    MetaDataFieldList sel;
    sel.setAll();
    initTableFields(sel);
  }
}
