/***************************************************************************
**
**  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 <GeopsyGui.h>

#include "SortKeys.h"

static const char* sortKeyAscending=QT_TRANSLATE_NOOP("SortKeys", "ascending");
static const char* sortKeyDescending=QT_TRANSLATE_NOOP("SortKeys", "descending");

// TODO rewrite with Model structure, add up and down buttons

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

QWidget *SortKeysDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &,
                                     const QModelIndex &index) const
{
  switch(index.column()) {
  case 0: {
      QComboBox *w=new QComboBox (parent);
      w->addItems(_keyList);
      return w;
    }
  case 1: {
      QLineEdit * w=new QLineEdit(parent);
      return w;
    }
  case 2: {
      QComboBox *w=new QComboBox (parent);
      w->addItem(tr(sortKeyAscending));
      w->addItem(tr(sortKeyDescending));
      return w;
    }
  default:
    break;
  }
  return nullptr;
}

void SortKeysDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
  TRACE;
  switch(index.column()) {
  case 0:
  case 2: {
      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: {
      QLineEdit *w=qobject_cast<QLineEdit *>(editor);
      if(!w) return;
      w->setText(index.model()->data(index).toString());
      break;
    }
  default:
    break;
  }
}

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

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

  keyList->setColumnCount(3);
  QStringList hLabels;
  hLabels << tr("Key") << tr("Index") << tr("Order");
  keyList->setHorizontalHeaderLabels (hLabels);
  keyList->setSelectionBehavior(QAbstractItemView::SelectItems);
  keyList->setSelectionMode(QAbstractItemView::SingleSelection);
  keyList->setEditTriggers(QAbstractItemView::AllEditTriggers);
  keyList->setItemDelegate (new SortKeysDelegate(this));
#if(QT_VERSION > QT_VERSION_CHECK(5, 0, 0))
  keyList->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
#else
  keyList->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
#endif

  // Load choosen keys from registry
  QSettings& reg=CoreApplication::instance()->settings();
  QStringList keysStr=reg.value("Sort Keys").toStringList();
  SortKey::clear();
  for(QStringList::Iterator it=keysStr.begin(); it!=keysStr.end(); ++it) {
    QString key=(*it).mid(1);
    if((*it)[0]=='-') {
      SortKey::add(SortKey(MetaDataFactory::instance()->index(key), true));
    } else {
      SortKey::add(SortKey(MetaDataFactory::instance()->index(key), false));
    }
  }

  int nKeys=SortKey::count();
  keyList->setRowCount(nKeys);
  QTableWidgetItem * item;
  for(int i=0; i<nKeys;++i) {
    const SortKey& key=SortKey::at(i);

    item=new QTableWidgetItem(MetaDataFactory::instance()->baseName(key));
    keyList->setItem(i, 0, item);

    item=new QTableWidgetItem(key.index());
    setIndexState(item, key);
    keyList->setItem(i, 1, item);

    item=new QTableWidgetItem();
    if(key.reversed())
      item->setText(tr(sortKeyDescending));
    else
      item->setText(tr(sortKeyAscending));
    keyList->setItem(i, 2, item);

    keyList->resizeRowToContents(i);
  }
  if(keyList->rowCount() > 0) {
    keyList->setCurrentItem(keyList->item(0,0));
    insertBut->setEnabled(true);
    deleteBut->setEnabled(true);
  }
  keyList->resizeColumnToContents (1);
  keyList->resizeColumnToContents (2);
}

void SortKeys::on_keyList_cellChanged (int row, int column)
{
  TRACE;
  if(column==0) {
    QTableWidgetItem * itemKey=keyList->item(row, 0);
    QTableWidgetItem * itemIndex=keyList->item(row, 1);
    if(itemKey && itemIndex) {
      setIndexState(itemIndex, MetaDataFactory::instance()->index(itemKey->text()));
    }
  }
}

void SortKeys::setIndexState(QTableWidgetItem * item, const MetaDataIndex& index)
{
  TRACE;
  if(MetaDataFactory::instance()->isArray(index)) {
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable);
  } else {
    item->setFlags(0);
  }
  keyList->reset();
}

void SortKeys::getKeys()
{
  TRACE;
  // Get choosen keys in Signal::_keys
  int n=keyList->rowCount();
  SortKey::clear();
  for(int i=0;i < n;i++ ) {
    QString key=keyList->item(i, 0)->text();
    MetaDataIndex index(MetaDataFactory::instance()->index(key));
    index.setIndex(keyList->item(i, 1)->text());
    if(keyList->item(i, 2)->text()==tr(sortKeyDescending))
      SortKey::add(SortKey(index, true));
    else
      SortKey::add(SortKey(index, false));
  }
  // Save choosen keys to registry
  QStringList keysStr;
  for(int i=0; i < n; i++ ) {
    const SortKey& key=SortKey::at(i);
    if(key.reversed()) {
      keysStr.append("-"+MetaDataFactory::instance()->name(key));
    } else {
      keysStr.append("+"+MetaDataFactory::instance()->name(key));
    }
  }
  QSettings& reg=CoreApplication::instance()->settings();
  reg.setValue("Sort Keys", keysStr);
}

void SortKeys::on_addBut_clicked()
{
  TRACE;
  int n=keyList->rowCount();
  keyList->setRowCount(n + 1);

  QTableWidgetItem * item;
  item=new QTableWidgetItem(MetaDataFactory::instance()->name(MetaDataFactory::Name));
  keyList->setItem(n, 0, item);
  item=new QTableWidgetItem("0");
  setIndexState (item, MetaDataFactory::Name);
  keyList->setItem(n, 1, item);
  item=new QTableWidgetItem(sortKeyAscending);
  keyList->setItem(n, 2, item);

  keyList->resizeRowToContents(n);
  insertBut->setEnabled(true);
  deleteBut->setEnabled(true);
  keyList->clearSelection();
  keyList->setCurrentItem(keyList->item(n, 0));
}

void SortKeys::on_insertBut_clicked()
{
  TRACE;
  int n=keyList->currentRow();
  if(n >= 0) {
    keyList->insertRow(n);

    QTableWidgetItem * item;
    item=new QTableWidgetItem(MetaDataFactory::instance()->name(MetaDataFactory::Name));
    keyList->setItem(n, 0, item);
    item=new QTableWidgetItem("0");
    setIndexState (item, MetaDataFactory::Name);
    keyList->setItem(n, 1, item);
    item=new QTableWidgetItem(sortKeyAscending);
    keyList->setItem(n, 2, item);

    keyList->resizeRowToContents(n);
    keyList->clearSelection();
    keyList->setCurrentItem(keyList->item(n, 0));
  }
}

void SortKeys::on_deleteBut_clicked()
{
  TRACE;
  int n=keyList->currentRow();
  keyList->QTableWidget::removeRow(n);
  if(keyList->rowCount()==0) {
    insertBut->setEnabled(false);
    deleteBut->setEnabled(false);
  } else {
    keyList->clearSelection();
    if(n>=keyList->rowCount()) n=keyList->rowCount()-1;
    keyList->setCurrentItem(keyList->item(n, 0));
  }
}
