/***************************** LICENSE START ***********************************

 Copyright 2013 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQLayerSuperPage.h"

//#include <QDebug>

#include <QAction>
#include <QDropEvent>
#include <QMenu>

#include "Assertions.hpp"
#include "Root.h"

//==================================================================
//
//	MvQLayerSuperPageModel
//
//==================================================================

MvQLayerSuperPageModel::MvQLayerSuperPageModel(QObject* parent) :
    QAbstractItemModel(parent)
{
}

MvQLayerSuperPageModel::~MvQLayerSuperPageModel()
{
    icons_.clear();
}

int MvQLayerSuperPageModel::columnCount(const QModelIndex& parent) const
{
    //if ( parent.isValid() )
    //   qDebug() << "MvQLayerSuperPageModel::columnCount 0";
    //else
    //      qDebug() << "MvQLayerSuperPageModel::columnCount 1";

    return parent.isValid() ? 0 : 1;
}

int MvQLayerSuperPageModel::rowCount(const QModelIndex& index) const
{
    if (!index.isValid())
        return icons_.count();
    else
        return 0;
}

QVariant MvQLayerSuperPageModel::data(const QModelIndex& index, int role) const
{
    if (role != Qt::DisplayRole && role != Qt::DecorationRole &&
        role != Qt::ForegroundRole && role != Qt::UserRole &&
        role != Qt::FontRole)
        return QVariant();

    if (!index.isValid())
        return QVariant();

    if (index.row() < 0 || index.row() >= icons_.count())
        return QVariant();

    MvQLayerContentsIcon icon = icons_[index.row()];

    //qDebug() << "MvQLayerSuperPageModel::data " << icon.name() << icon.type() << icon.id();

    switch (role) {
        case Qt::DecorationRole: {  //qDebug() << "DecorationRole";
            return icon.pixmap();
        }

        case Qt::DisplayRole: {  //qDebug() << "DisplayRole";
            return icon.name();
        }

            //      case Qt::UserRole:
            //         return icon->path();
        default: {  //qDebug() << "default";
            break;
        }
    }

    return QVariant();
}


QModelIndex MvQLayerSuperPageModel::index(int row, int column, const QModelIndex& /*parent */) const
{
    return createIndex(row, column, (void*)0);
}

QModelIndex MvQLayerSuperPageModel::parent(const QModelIndex& /*index*/) const
{
    return QModelIndex();
}

void MvQLayerSuperPageModel::setIcons(MvIconList& iconList)
{
    // Clear current list of icons
    beginResetModel();
    icons_.clear();

    // Add new icons
    auto lCursor = iconList.begin();
    while (lCursor != iconList.end()) {
        MvIcon mvicon = *lCursor;
        MvQLayerContentsIcon icon(QString(mvicon.IconName()), QString(mvicon.IconClass()), QString::number(mvicon.Id()), false);

        icons_ << icon;
        ++lCursor;
    }

    endResetModel();
}

MvQLayerContentsIcon* MvQLayerSuperPageModel::indexToIcon(const QModelIndex& index)
{
    MvQLayerContentsIcon* icon = 0;
    if (!index.isValid() || index.column() < 0 || index.column() > icons_.count())
        return icon;

    icon = &icons_[index.row()];

    return icon;
}

#if 0
bool MvQLayerSuperPageModel::add( const MvQLayerContentsIcon& icon )
{
   if( icons_.contains(icon) )
      return false;

   beginResetModel();
   icons_ << icon;
   endResetModel();

   return true;
}

void MvQLayerSuperPageModel::remove( const MvQLayerContentsIcon& icon )
{
   beginResetModel();
   icons_.removeAll(icon);
   endResetModel();
}
#endif

void MvQLayerSuperPageModel::reset()
{
    // Get Presentable SuperPage and the DataBase
    Presentable* pres = Root::Instance().FindSuperPage();
    assert(pres != nullptr);  // Root::Instance().FindSuperPage() can return a NULL pointer
    MvIconDataBase& dataBase = pres->IconDataBase();

    // Retrieve icons from the DataBase
    MvIconList iconList;
    dataBase.RetrieveIcon(presentableId(), iconList);

    // Update list of icons
    setIcons(iconList);
}

//=================================================================
//
//	MvQLayerSuperPageView
//
//=================================================================

MvQLayerSuperPageView::MvQLayerSuperPageView(MvQLayerSuperPageModel* model, QWidget* parent) :
    QListView(parent),
    model_(model)
{
    // Set behaviour
    setViewMode(QListView::IconMode);
    setFlow(QListView::LeftToRight);
    setMovement(QListView::Snap);
    setWrapping(false);
    setResizeMode(QListView::Adjust);
    //   setIconSize(QSize(48, 48));
    //   setMaximumHeight(75);
    setSpacing(5);

    QFont font;
    QFontMetrics fm(font);
    setMaximumHeight(fm.size(Qt::TextExpandTabs, "A").height() + 32 + 10 + 5 + 10);

    // Double click
    connect(this, SIGNAL(doubleClicked(QModelIndex)),
            this, SLOT(slotDoubleClickItem(QModelIndex)));

    // Context menu
    createContextMenu();
    setContextMenuPolicy(Qt::ActionsContextMenu);
    //   connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
    //           this, SLOT(slotContextMenu(const QPoint&)));

    // Drag and Drop settings
    setMouseTracking(true);
    setAcceptDrops(true);
    setDragEnabled(true);
    setDropIndicatorShown(true);
    setDragDropMode(QAbstractItemView::DragDrop);

    setModel(model);
}

MvQLayerSuperPageView::~MvQLayerSuperPageView()
{
    foreach (QAction* ac, actions_) {
        delete ac;
        ac = 0;
    }
}

void MvQLayerSuperPageView::slotDoubleClickItem(const QModelIndex& index)
{
    if (!index.isValid())
        return;

    // Get icon from the model
    MvQLayerContentsIcon* icon = model_->indexToIcon(index);
    if (!icon)
        return;

    // Start editor
    icon->startEditor();
}

#if 0
void MvQLayerSuperPageView::slotContextMenu(const QPoint& pos)
{
   // Get index from position
   QModelIndex index = this->indexAt(pos); 
   if( !index.isValid() )
      return;

   // Get icon from the model
   MvQLayerContentsIcon *icon = model_->indexToIcon(index);
   if(!icon)
      return;

   //Insert new key
   QList<QAction*> actions;
   QAction *actionEdit = new QAction(this);
   actionEdit->setObjectName(QString::fromUtf8("actionEdit"));
   actionEdit->setText(tr("Edit in Plot"));
   QFont font = actionEdit->font();
   font.setWeight(QFont::Bold);
   actionEdit->setFont(font);
   actionEdit->setShortcut(QKeySequence(tr("Ctrl+E")));
   actions.append(actionEdit);
   if(!icon->canBeEdited())
      actionEdit->setEnabled(false); 

   //Inser new key
   QAction *actionSave = new QAction(this);
   actionSave->setObjectName(QString::fromUtf8("actionSave"));
   actionSave->setText(tr("Save to Disk"));
//   actionSave->setShortcut(QKeySequence(QKeySequence::Save));
   actionSave->setShortcut(QKeySequence::Save);
   actions.append(actionSave);
   if(!icon->canBeSaved())
      actionSave->setEnabled(false); 

   QAction *actionDelete = new QAction(this);
   actionDelete->setObjectName(QString::fromUtf8("actionDelete"));
   actionDelete->setText(tr("Remove from Plot"));
   actionDelete->setShortcuts(QKeySequence::Delete);
   actions.append(actionDelete);
   if(!icon->canBeDeleted())
      actionDelete->setEnabled(false); 

   QAction *res = QMenu::exec(actions,this->mapToGlobal(pos));   
   if(res == actionEdit)
      icon->startEditor();
   else if(res == actionSave)
      icon->saveIcon();
   else if(res == actionDelete)
      icon->deleteIcon();

   foreach(QAction *ac,actions)
      delete ac;
}
#else
void MvQLayerSuperPageView::createContextMenu()
{
    // Insert Edit key
    actionEdit_ = new QAction(this);
    actionEdit_->setObjectName(QString::fromUtf8("actionEdit"));
    actionEdit_->setText(tr("Edit in Plot"));
    QFont font = actionEdit_->font();
    font.setWeight(QFont::Bold);
    actionEdit_->setFont(font);
    actionEdit_->setShortcut(tr("Ctrl+E"));
    actionEdit_->setShortcutContext(Qt::WidgetWithChildrenShortcut);
    actions_.append(actionEdit_);

    addAction(actionEdit_);
    connect(actionEdit_, SIGNAL(triggered()), this, SLOT(slotEdit()));

    // Insert Save key
    actionSave_ = new QAction(this);
    actionSave_->setObjectName(QString::fromUtf8("actionSave"));
    actionSave_->setText(tr("Save to Disk"));
    actionSave_->setShortcut(QKeySequence::Save);
    actionSave_->setShortcutContext(Qt::WidgetWithChildrenShortcut);
    actions_.append(actionSave_);

    addAction(actionSave_);
    connect(actionSave_, SIGNAL(triggered()), this, SLOT(slotSave()));

    // Insert Save As key
    actionSaveAs_ = new QAction(this);
    actionSaveAs_->setObjectName(QString::fromUtf8("actionSaveAs"));
    actionSaveAs_->setText(tr("Save As"));
    actionSaveAs_->setShortcut(QKeySequence::SaveAs);
    actionSaveAs_->setShortcutContext(Qt::WidgetWithChildrenShortcut);
    actions_.append(actionSaveAs_);

    addAction(actionSaveAs_);
    connect(actionSaveAs_, SIGNAL(triggered()), this, SLOT(slotSaveAs()));

    // Insert Delete key
    actionDelete_ = new QAction(this);
    actionDelete_->setObjectName(QString::fromUtf8("actionDelete"));
    actionDelete_->setText(tr("Remove from Plot"));
    actionDelete_->setShortcuts(QKeySequence::Delete);
    actionDelete_->setShortcutContext(Qt::WidgetWithChildrenShortcut);
    actions_.append(actionDelete_);

    addAction(actionDelete_);
    connect(actionDelete_, SIGNAL(triggered()), this, SLOT(slotDelete()));
}

void MvQLayerSuperPageView::currentChanged(const QModelIndex& current, const QModelIndex& previous)
{
    // Get icon from the model
    MvQLayerContentsIcon* icon = model_->indexToIcon(current);
    if (!icon)
        return;

    // Check options visibility
    bool bvis = icon->canBeEdited() ? true : false;
    actionEdit_->setEnabled(bvis);

    bvis = icon->canBeSaved() ? true : false;
    actionSave_->setEnabled(bvis);

    bvis = icon->canBeSavedAs() ? true : false;
    actionSaveAs_->setEnabled(bvis);

    bvis = icon->canBeDeleted() ? true : false;
    actionDelete_->setEnabled(bvis);

    QListView::currentChanged(current, previous);
}

void MvQLayerSuperPageView::slotEdit()
{
    // Get selected index
    QModelIndex index = currentIndex();

    // Get icon from the model
    MvQLayerContentsIcon* icon = model_->indexToIcon(index);
    if (!icon)
        return;

    // Edit icon
    icon->startEditor();
}

void MvQLayerSuperPageView::slotSave()
{
    // Get selected index
    QModelIndex index = currentIndex();

    // Get icon from the model
    MvQLayerContentsIcon* icon = model_->indexToIcon(index);
    if (!icon)
        return;

    // Save icon
    icon->saveIcon();
}

void MvQLayerSuperPageView::slotSaveAs()
{
    // Get selected index
    QModelIndex index = currentIndex();

    // Get icon from the model
    MvQLayerContentsIcon* icon = model_->indexToIcon(index);
    if (!icon)
        return;

    // Save icon
    icon->saveAsIcon();
}

void MvQLayerSuperPageView::slotDelete()
{
    // Get selected index
    QModelIndex index = currentIndex();

    // Get icon from the model
    MvQLayerContentsIcon* icon = model_->indexToIcon(index);
    if (!icon)
        return;

    // Delete icon
    icon->deleteIcon();
}
#endif

void MvQLayerSuperPageView::dragEnterEvent(QDragEnterEvent* event)
{
    if ((event->proposedAction() == Qt::CopyAction ||
         event->proposedAction() == Qt::MoveAction))
        event->accept();
    else
        event->ignore();
}

void MvQLayerSuperPageView::dragLeaveEvent(QDragLeaveEvent* event)
{
    //   layerId_ = -1;   // initialise with a non-valid value
    //   model_->setHighlightedLayer(QModelIndex(),layerId_);
    event->accept();
}

void MvQLayerSuperPageView::dragMoveEvent(QDragMoveEvent* event)
{
    if ((event->proposedAction() == Qt::CopyAction ||
         event->proposedAction() == Qt::MoveAction))
        event->accept();
    else
        event->ignore();
}

void MvQLayerSuperPageView::dropEvent(QDropEvent* event)
{
    if (event->proposedAction() != Qt::CopyAction &&
        event->proposedAction() != Qt::MoveAction) {
        event->ignore();
        return;
    }

    // Get dropped icon
    MvQDrop drop(event);
    if (drop.hasData()) {
        // Get index from the dropped position (the target icon)
        //      QModelIndex index = this->indexAt(event->pos());
        //      if( !index.isValid() )
        //      {
        //         COUT << "Drop not accepted: MvQLayerView::dropEvent" << std::endl;
        //         return;
        //      }

        // To handle the dropped icon
        emit iconDropped(drop);

        event->accept();
        return;
    }
    else {
        // Relayed base class
        QListView::dropEvent(event);
    }
}
