/*============================================================================
  CMake - Cross Platform Makefile Generator
  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium

  Distributed under the OSI-approved BSD License (the "License");
  see accompanying file Copyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the License for more information.
============================================================================*/

#include "QCMakeCacheView.h"

#include <QHBoxLayout>
#include <QHeaderView>
#include <QEvent>
#include <QStyle>
#include <QKeyEvent>
#include <QSortFilterProxyModel>
#include <QMetaProperty>
#include <QApplication>

#include "QCMakeWidgets.h"

// filter for searches
class QCMakeSearchFilter : public QSortFilterProxyModel
{
public:
  QCMakeSearchFilter(QObject* o) : QSortFilterProxyModel(o) {}
protected:
  bool filterAcceptsRow(int row, const QModelIndex& p) const
    {
    QStringList strs;
    const QAbstractItemModel* m = this->sourceModel();
    QModelIndex idx = m->index(row, 0, p);

    // if there are no children, get strings for column 0 and 1
    if(!m->hasChildren(idx))
      {
      strs.append(m->data(idx).toString());
      idx = m->index(row, 1, p);
      strs.append(m->data(idx).toString());
      }
    else
      {
      // get strings for children entries to compare with
      // instead of comparing with the parent
      int num = m->rowCount(idx);
      for(int i=0; i<num; i++)
        {
        QModelIndex tmpidx = m->index(i, 0, idx);
        strs.append(m->data(tmpidx).toString());
        tmpidx = m->index(i, 1, idx);
        strs.append(m->data(tmpidx).toString());
        }
      }

    // check all strings for a match
    foreach(QString str, strs)
      {
      if(str.contains(this->filterRegExp()))
        {
        return true;
        }
      }

    return false;
    }
};

// filter for searches
class QCMakeAdvancedFilter : public QSortFilterProxyModel
{
public:
  QCMakeAdvancedFilter(QObject* o)
    : QSortFilterProxyModel(o), ShowAdvanced(false) {}

  void setShowAdvanced(bool f)
  {
    this->ShowAdvanced = f;
    this->invalidate();
  }
  bool showAdvanced() const { return this->ShowAdvanced; }

protected:

  bool ShowAdvanced;

  bool filterAcceptsRow(int row, const QModelIndex& p) const
    {
    const QAbstractItemModel* m = this->sourceModel();
    QModelIndex idx = m->index(row, 0, p);

    // if there are no children
    if(!m->hasChildren(idx))
      {
      bool adv = m->data(idx, QCMakeCacheModel::AdvancedRole).toBool();
      if(!adv || (adv && this->ShowAdvanced))
        {
        return true;
        }
      return false;
      }

    // check children
    int num = m->rowCount(idx);
    for(int i=0; i<num; i++)
      {
      bool accept = this->filterAcceptsRow(i, idx);
      if(accept)
        {
        return true;
        }
      }
    return false;
    }
};

QCMakeCacheView::QCMakeCacheView(QWidget* p)
  : QTreeView(p)
{
  // hook up our model and search/filter proxies
  this->CacheModel = new QCMakeCacheModel(this);
  this->AdvancedFilter = new QCMakeAdvancedFilter(this);
  this->AdvancedFilter->setSourceModel(this->CacheModel);
  this->AdvancedFilter->setDynamicSortFilter(true);
  this->SearchFilter = new QCMakeSearchFilter(this);
  this->SearchFilter->setSourceModel(this->AdvancedFilter);
  this->SearchFilter->setFilterCaseSensitivity(Qt::CaseInsensitive);
  this->SearchFilter->setDynamicSortFilter(true);
  this->setModel(this->SearchFilter);

  // our delegate for creating our editors
  QCMakeCacheModelDelegate* delegate = new QCMakeCacheModelDelegate(this);
  this->setItemDelegate(delegate);

  this->setUniformRowHeights(true);

  this->setEditTriggers(QAbstractItemView::AllEditTriggers);

  // tab, backtab doesn't step through items
  this->setTabKeyNavigation(false);

  this->setRootIsDecorated(false);
}

bool QCMakeCacheView::event(QEvent* e)
{
  if(e->type() == QEvent::Show)
    {
    this->header()->setDefaultSectionSize(this->viewport()->width()/2);
    }
  return QTreeView::event(e);
}

QCMakeCacheModel* QCMakeCacheView::cacheModel() const
{
  return this->CacheModel;
}

QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
  Qt::KeyboardModifiers mod)
{
  // want home/end to go to begin/end of rows, not columns
  if(act == MoveHome)
    {
    return this->model()->index(0, 1);
    }
  else if(act == MoveEnd)
    {
    return this->model()->index(this->model()->rowCount()-1, 1);
    }
  return QTreeView::moveCursor(act, mod);
}

void QCMakeCacheView::setShowAdvanced(bool s)
{
#if QT_VERSION >= 040300
  // new 4.3 API that needs to be called.  what about an older Qt?
  this->SearchFilter->invalidate();
#endif

  this->AdvancedFilter->setShowAdvanced(s);
}

bool QCMakeCacheView::showAdvanced() const
{
  return this->AdvancedFilter->showAdvanced();
}

void QCMakeCacheView::setSearchFilter(const QString& s)
{
  this->SearchFilter->setFilterFixedString(s);
}

QCMakeCacheModel::QCMakeCacheModel(QObject* p)
  : QStandardItemModel(p),
    EditEnabled(true),
    NewPropertyCount(0),
    View(FlatView)
{
  this->ShowNewProperties = true;
  QStringList labels;
  labels << tr("Name") << tr("Value");
  this->setHorizontalHeaderLabels(labels);
}

QCMakeCacheModel::~QCMakeCacheModel()
{
}

static uint qHash(const QCMakeProperty& p)
{
  return qHash(p.Key);
}

void QCMakeCacheModel::setShowNewProperties(bool f)
{
  this->ShowNewProperties = f;
}

void QCMakeCacheModel::clear()
{
  this->QStandardItemModel::clear();
  this->NewPropertyCount = 0;

  QStringList labels;
  labels << tr("Name") << tr("Value");
  this->setHorizontalHeaderLabels(labels);
}

void QCMakeCacheModel::setProperties(const QCMakePropertyList& props)
{
  QSet<QCMakeProperty> newProps, newProps2;

  if(this->ShowNewProperties)
    {
    newProps = props.toSet();
    newProps2 = newProps;
    QSet<QCMakeProperty> oldProps = this->properties().toSet();
    oldProps.intersect(newProps);
    newProps.subtract(oldProps);
    newProps2.subtract(newProps);
    }
  else
    {
    newProps2 = props.toSet();
    }

  bool b = this->blockSignals(true);

  this->clear();
  this->NewPropertyCount = newProps.size();

  if(View == FlatView)
  {
    QCMakePropertyList newP = newProps.toList();
    QCMakePropertyList newP2 = newProps2.toList();
    qSort(newP);
    qSort(newP2);
    int row_count = 0;
    foreach(QCMakeProperty p, newP)
    {
      this->insertRow(row_count);
      this->setPropertyData(this->index(row_count, 0), p, true);
      row_count++;
    }
    foreach(QCMakeProperty p, newP2)
    {
      this->insertRow(row_count);
      this->setPropertyData(this->index(row_count, 0), p, false);
      row_count++;
    }
  }
  else if(this->View == GroupView)
  {
    QMap<QString, QCMakePropertyList> newPropsTree;
    this->breakProperties(newProps, newPropsTree);
    QMap<QString, QCMakePropertyList> newPropsTree2;
    this->breakProperties(newProps2, newPropsTree2);

    QStandardItem* root = this->invisibleRootItem();

    foreach(QString key, newPropsTree.keys())
      {
      QCMakePropertyList props2 = newPropsTree[key];

      QList<QStandardItem*> parentItems;
      parentItems.append(
        new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key)
        );
      parentItems.append(new QStandardItem());
      parentItems[0]->setData(QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
      parentItems[1]->setData(QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
      parentItems[0]->setData(1, GroupRole);
      parentItems[1]->setData(1, GroupRole);
      root->appendRow(parentItems);

      int num = props2.size();
      for(int i=0; i<num; i++)
        {
        QCMakeProperty prop = props2[i];
        QList<QStandardItem*> items;
        items.append(new QStandardItem());
        items.append(new QStandardItem());
        parentItems[0]->appendRow(items);
        this->setPropertyData(this->indexFromItem(items[0]), prop, true);
        }
      }

    foreach(QString key, newPropsTree2.keys())
      {
      QCMakePropertyList props2 = newPropsTree2[key];

      QStandardItem* parentItem =
        new QStandardItem(key.isEmpty() ? tr("Ungrouped Entries") : key);
      root->appendRow(parentItem);
      parentItem->setData(1, GroupRole);

      int num = props2.size();
      for(int i=0; i<num; i++)
        {
        QCMakeProperty prop = props2[i];
        QList<QStandardItem*> items;
        items.append(new QStandardItem());
        items.append(new QStandardItem());
        parentItem->appendRow(items);
        this->setPropertyData(this->indexFromItem(items[0]), prop, false);
        }
      }
  }

  this->blockSignals(b);
  this->reset();
}

QCMakeCacheModel::ViewType QCMakeCacheModel::viewType() const
{
  return this->View;
}

void QCMakeCacheModel::setViewType(QCMakeCacheModel::ViewType t)
{
  this->View = t;

  QCMakePropertyList props = this->properties();
  QCMakePropertyList oldProps;
  int numNew = this->NewPropertyCount;
  int numTotal = props.count();
  for(int i=numNew; i<numTotal; i++)
  {
    oldProps.append(props[i]);
  }

  bool b = this->blockSignals(true);
  this->clear();
  this->setProperties(oldProps);
  this->setProperties(props);
  this->blockSignals(b);
  this->reset();
}

void QCMakeCacheModel::setPropertyData(const QModelIndex& idx1,
    const QCMakeProperty& prop, bool isNew)
{
  QModelIndex idx2 = idx1.sibling(idx1.row(), 1);

  this->setData(idx1, prop.Key, Qt::DisplayRole);
  this->setData(idx1, prop.Help, QCMakeCacheModel::HelpRole);
  this->setData(idx1, prop.Type, QCMakeCacheModel::TypeRole);
  this->setData(idx1, prop.Advanced, QCMakeCacheModel::AdvancedRole);

  if(prop.Type == QCMakeProperty::BOOL)
  {
    int check = prop.Value.toBool() ? Qt::Checked : Qt::Unchecked;
    this->setData(idx2, check, Qt::CheckStateRole);
  }
  else
  {
    this->setData(idx2, prop.Value, Qt::DisplayRole);
  }
  this->setData(idx2, prop.Help, QCMakeCacheModel::HelpRole);

  if (!prop.Strings.isEmpty())
  {
    this->setData(idx1, prop.Strings, QCMakeCacheModel::StringsRole);
  }

  if(isNew)
  {
    this->setData(idx1, QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
    this->setData(idx2, QBrush(QColor(255,100,100)), Qt::BackgroundColorRole);
  }
}

void QCMakeCacheModel::getPropertyData(const QModelIndex& idx1,
    QCMakeProperty& prop) const
{
  QModelIndex idx2 = idx1.sibling(idx1.row(), 1);

  prop.Key = this->data(idx1, Qt::DisplayRole).toString();
  prop.Help = this->data(idx1, HelpRole).toString();
  prop.Type = static_cast<QCMakeProperty::PropertyType>(this->data(idx1, TypeRole).toInt());
  prop.Advanced = this->data(idx1, AdvancedRole).toBool();
  prop.Strings = this->data(idx1, QCMakeCacheModel::StringsRole).toStringList();
  if(prop.Type == QCMakeProperty::BOOL)
  {
    int check = this->data(idx2, Qt::CheckStateRole).toInt();
    prop.Value = check == Qt::Checked;
  }
  else
  {
    prop.Value = this->data(idx2, Qt::DisplayRole).toString();
  }
}

QString QCMakeCacheModel::prefix(const QString& s)
{
  QString prefix = s.section('_', 0, 0);
  if(prefix == s)
    {
    prefix = QString();
    }
  return prefix;
}

void QCMakeCacheModel::breakProperties(const QSet<QCMakeProperty>& props,
                     QMap<QString, QCMakePropertyList>& result)
{
  QMap<QString, QCMakePropertyList> tmp;
  // return a map of properties grouped by prefixes, and sorted
  foreach(QCMakeProperty p, props)
    {
    QString prefix = QCMakeCacheModel::prefix(p.Key);
    tmp[prefix].append(p);
    }
  // sort it and re-org any properties with only one sub item
  QCMakePropertyList reorgProps;
  QMap<QString, QCMakePropertyList>::iterator iter;
  for(iter = tmp.begin(); iter != tmp.end();)
    {
    if(iter->count() == 1)
      {
      reorgProps.append((*iter)[0]);
      iter = tmp.erase(iter);
      }
    else
      {
      qSort(*iter);
      ++iter;
      }
    }
  if(reorgProps.count())
    {
    tmp[QString()] += reorgProps;
    }
  result = tmp;
}

QCMakePropertyList QCMakeCacheModel::properties() const
{
  QCMakePropertyList props;

  if(!this->rowCount())
    {
    return props;
    }

  QList<QModelIndex> idxs;
  idxs.append(this->index(0,0));

  // walk the entire model for property entries
  // this works regardless of a flat view or a tree view
  while(!idxs.isEmpty())
  {
    QModelIndex idx = idxs.last();
    if(this->hasChildren(idx) && this->rowCount(idx))
    {
      idxs.append(this->index(0,0, idx));
    }
    else
    {
      if(!data(idx, GroupRole).toInt())
      {
        // get data
        QCMakeProperty prop;
        this->getPropertyData(idx, prop);
        props.append(prop);
      }

      // go to the next in the tree
      while(!idxs.isEmpty() && (
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
        (idxs.last().row()+1) >= rowCount(idxs.last().parent()) ||
#endif
        !idxs.last().sibling(idxs.last().row()+1, 0).isValid()))
      {
        idxs.removeLast();
      }
      if(!idxs.isEmpty())
      {
        idxs.last() = idxs.last().sibling(idxs.last().row()+1, 0);
      }
    }
  }

  return props;
}

bool QCMakeCacheModel::insertProperty(QCMakeProperty::PropertyType t,
                      const QString& name, const QString& description,
                      const QVariant& value, bool advanced)
{
  QCMakeProperty prop;
  prop.Key = name;
  prop.Value = value;
  prop.Help = description;
  prop.Type = t;
  prop.Advanced = advanced;

  //insert at beginning
  this->insertRow(0);
  this->setPropertyData(this->index(0,0), prop, true);
  this->NewPropertyCount++;
  return true;
}

void QCMakeCacheModel::setEditEnabled(bool e)
{
  this->EditEnabled = e;
}

bool QCMakeCacheModel::editEnabled() const
{
  return this->EditEnabled;
}

int QCMakeCacheModel::newPropertyCount() const
{
  return this->NewPropertyCount;
}

Qt::ItemFlags QCMakeCacheModel::flags (const QModelIndex& idx) const
{
  Qt::ItemFlags f = QStandardItemModel::flags(idx);
  if(!this->EditEnabled)
    {
    f &= ~Qt::ItemIsEditable;
    return f;
    }
  if(QCMakeProperty::BOOL == this->data(idx, TypeRole).toInt())
    {
    f |= Qt::ItemIsUserCheckable;
    }
  return f;
}

QModelIndex QCMakeCacheModel::buddy(const QModelIndex& idx) const
{
  if(!this->hasChildren(idx) &&
     this->data(idx, TypeRole).toInt() != QCMakeProperty::BOOL)
  {
    return this->index(idx.row(), 1, idx.parent());
  }
  return idx;
}

QCMakeCacheModelDelegate::QCMakeCacheModelDelegate(QObject* p)
  : QItemDelegate(p), FileDialogFlag(false)
{
}

void QCMakeCacheModelDelegate::setFileDialogFlag(bool f)
{
  this->FileDialogFlag = f;
}

QWidget* QCMakeCacheModelDelegate::createEditor(QWidget* p,
    const QStyleOptionViewItem&, const QModelIndex& idx) const
{
  QModelIndex var = idx.sibling(idx.row(), 0);
  int type = var.data(QCMakeCacheModel::TypeRole).toInt();
  if(type == QCMakeProperty::BOOL)
    {
    return NULL;
    }
  else if(type == QCMakeProperty::PATH)
    {
    QCMakePathEditor* editor =
      new QCMakePathEditor(p,
      var.data(Qt::DisplayRole).toString());
    QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
        SLOT(setFileDialogFlag(bool)));
    return editor;
    }
  else if(type == QCMakeProperty::FILEPATH)
    {
    QCMakeFilePathEditor* editor =
      new QCMakeFilePathEditor(p,
      var.data(Qt::DisplayRole).toString());
    QObject::connect(editor, SIGNAL(fileDialogExists(bool)), this,
        SLOT(setFileDialogFlag(bool)));
    return editor;
    }
  else if(type == QCMakeProperty::STRING &&
          var.data(QCMakeCacheModel::StringsRole).isValid())
    {
    QCMakeComboBox* editor =
      new QCMakeComboBox(p, var.data(QCMakeCacheModel::StringsRole).toStringList());
    editor->setFrame(false);
    return editor;
    }

  QLineEdit* editor = new QLineEdit(p);
  editor->setFrame(false);
  return editor;
}

bool QCMakeCacheModelDelegate::editorEvent(QEvent* e, QAbstractItemModel* model,
       const QStyleOptionViewItem& option, const QModelIndex& index)
{
  Qt::ItemFlags flags = model->flags(index);
  if (!(flags & Qt::ItemIsUserCheckable) || !(option.state & QStyle::State_Enabled)
      || !(flags & Qt::ItemIsEnabled))
    {
    return false;
    }

  QVariant value = index.data(Qt::CheckStateRole);
  if (!value.isValid())
    {
    return false;
    }

  if ((e->type() == QEvent::MouseButtonRelease)
      || (e->type() == QEvent::MouseButtonDblClick))
    {
    // eat the double click events inside the check rect
    if (e->type() == QEvent::MouseButtonDblClick)
      {
      return true;
      }
    }
  else if (e->type() == QEvent::KeyPress)
    {
    if(static_cast<QKeyEvent*>(e)->key() != Qt::Key_Space &&
       static_cast<QKeyEvent*>(e)->key() != Qt::Key_Select)
      {
      return false;
      }
    }
  else
    {
    return false;
    }

  Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
                          ? Qt::Unchecked : Qt::Checked);
  bool success = model->setData(index, state, Qt::CheckStateRole);
  if(success)
    {
    this->recordChange(model, index);
    }
  return success;
}

// Issue 205903 fixed in Qt 4.5.0.
// Can remove this function and FileDialogFlag when minimum Qt version is 4.5
bool QCMakeCacheModelDelegate::eventFilter(QObject* object, QEvent* evt)
{
  // workaround for what looks like a bug in Qt on Mac OS X
  // where it doesn't create a QWidget wrapper for the native file dialog
  // so the Qt library ends up assuming the focus was lost to something else

  if(evt->type() == QEvent::FocusOut && this->FileDialogFlag)
    {
    return false;
    }
  return QItemDelegate::eventFilter(object, evt);
}

void QCMakeCacheModelDelegate::setModelData(QWidget* editor,
  QAbstractItemModel* model, const QModelIndex& index ) const
{
  QItemDelegate::setModelData(editor, model, index);
  const_cast<QCMakeCacheModelDelegate*>(this)->recordChange(model, index);
}

QSize QCMakeCacheModelDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
  QSize sz = QItemDelegate::sizeHint(option, index);
  QStyle *style = QApplication::style();

  // increase to checkbox size
  QStyleOptionButton opt;
  opt.QStyleOption::operator=(option);
  sz = sz.expandedTo(style->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt, NULL).size());

  return sz;
}

QSet<QCMakeProperty> QCMakeCacheModelDelegate::changes() const
{
  return mChanges;
}

void QCMakeCacheModelDelegate::clearChanges()
{
  mChanges.clear();
}

void QCMakeCacheModelDelegate::recordChange(QAbstractItemModel* model, const QModelIndex& index)
{
  QModelIndex idx = index;
  QAbstractItemModel* mymodel = model;
  while(qobject_cast<QAbstractProxyModel*>(mymodel))
    {
    idx = static_cast<QAbstractProxyModel*>(mymodel)->mapToSource(idx);
    mymodel = static_cast<QAbstractProxyModel*>(mymodel)->sourceModel();
    }
  QCMakeCacheModel* cache_model = qobject_cast<QCMakeCacheModel*>(mymodel);
  if(cache_model && idx.isValid())
    {
    QCMakeProperty prop;
    idx = idx.sibling(idx.row(), 0);
    cache_model->getPropertyData(idx, prop);

    // clean out an old one
    QSet<QCMakeProperty>::iterator iter = mChanges.find(prop);
    if(iter != mChanges.end())
      {
      mChanges.erase(iter);
      }
    // now add the new item
    mChanges.insert(prop);
    }
}

