/*
 * Copyright 2014 Mihai Niculescu <q.quark@gmail.com>
 *
 * This file is part of EqualX Project (https://launchpad.net/equalx/)
 *
 * EqualX 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.
 *
 * EqualX 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <QDebug>
#include <QDragEnterEvent>
#include <QMessageBox>
#include <QMenu>
#include <QMimeData>
#include <QStandardItemModel>
#include <QUrl>

#include "File.h"
#include "FileInfo.h"
#include "Library/Library.h"

#include "BookmarksPanel/BookmarkItem.h"
#include "BookmarksPanel/BookmarksItemModel.h"
#include "BookmarksPanel/BookmarksViewItemDelegate.h"
#include "BookmarksPanel/BookmarksWidget.h"
#include "BookmarksPanel/DialogPreferencesFolder.h"
#include "BookmarksPanel/DialogPreferencesBookmark.h"

#include "ui_BookmarksWidget.h"

BookmarksWidget::BookmarksWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BookmarksWidget),
    mCopiedRow(),
    mIsCutActive(false)
{
    ui->setupUi(this);

    ui->widgetSearchImage->setHidden(true);

    mDgPreferencesFolder = new DialogPreferencesFolder(this);
    mDgPreferencesBookmark= new DialogPreferencesBookmark(this);

    // Bookmarks View Page
    mModel =  new BookmarksItemModel(LibraryManager::Instance());

    BookmarksViewItemDelegate *bviDelegate = new BookmarksViewItemDelegate(this);

    ui->treeView->setItemDelegate(bviDelegate);
    ui->treeView->setAlternatingRowColors(true);
    //ui->treeView->setHeaderHidden(true);
    ui->treeView->setContextMenuPolicy(Qt::ActionsContextMenu);
    ui->treeView->setSelectionMode(QAbstractItemView::SingleSelection);
    ui->treeView->setDragEnabled(true);
    ui->treeView->setAcceptDrops(true);
    ui->treeView->setDropIndicatorShown(true);
    ui->treeView->setDragDropMode(QAbstractItemView::InternalMove);
    ui->treeView->setExpandsOnDoubleClick ( true );
    ui->treeView->setItemsExpandable(true);

    ui->treeView->setModel(mModel);

    // Search Page
    mSearchModel = new QStandardItemModel(this);
    BookmarksViewItemDelegate *bviDelegate2 = new BookmarksViewItemDelegate(this);
    ui->listView->setItemDelegate(bviDelegate2);
    ui->listView->setModel(mSearchModel);


    setWindowTitle("Bookmarks");

    setupContextMenuActions();
    setupBookmarksSearchFields();

    connect(ui->treeView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClick(QModelIndex)) );
    connect(ui->listView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onDoubleClick(QModelIndex)) );
    connect(ui->bookmarkSearchEdit, SIGNAL(textChanged(QString)), this, SLOT(resetAutoSearchTimer(QString)) );
    connect(&mAutoSearchTimer, SIGNAL(timeout()), this, SLOT(searchBookmarks()) );


    setAcceptDrops(true);
}

BookmarksWidget::~BookmarksWidget()
{
    delete ui;
    mModel->deleteLater();
}

void BookmarksWidget::setupContextMenuActions()
{
    QAction* actOpen = new QAction("Open", ui->treeView);
    ui->treeView->addAction(actOpen);

    QAction* actSep1 = new QAction(ui->treeView);
    actSep1->setSeparator(true);
    ui->treeView->addAction(actSep1);

    QAction* actNewFolder = new QAction("New Folder", ui->treeView);
    ui->treeView->addAction(actNewFolder);

    QAction* actSep2 = new QAction(ui->treeView);
    actSep2->setSeparator(true);
    ui->treeView->addAction(actSep2);

    QAction* actCut = new QAction("Cut", ui->treeView);
    ui->treeView->addAction(actCut);

    QAction* actCopy = new QAction("Copy", ui->treeView);
    actCopy->setShortcut(Qt::CTRL | Qt::Key_C);
    ui->treeView->addAction(actCopy);

    QAction* actPaste = new QAction("Paste", ui->treeView);
    ui->treeView->addAction(actPaste);

    QAction* actSep3 = new QAction(ui->treeView);
    actSep3->setSeparator(true);
    ui->treeView->addAction(actSep3);

    QAction* actDelete = new QAction("Delete", ui->treeView);
    ui->treeView->addAction(actDelete);


    QAction* actSep4 = new QAction(ui->treeView);
    actSep4->setSeparator(true);
    ui->treeView->addAction(actSep4);

    QAction* actProp = new QAction("Properties", ui->treeView);
    ui->treeView->addAction(actProp);

    connect(actOpen, SIGNAL(triggered()), this, SLOT(onOpen()) );
    connect(actNewFolder, SIGNAL(triggered()), this, SLOT(onNewFolder()) );
    connect(actCut, SIGNAL(triggered()), this, SLOT(onCut()) );
    connect(actCopy, SIGNAL(triggered()), this, SLOT(onCopy()) );
    connect(actPaste, SIGNAL(triggered()), this, SLOT(onPaste()) );
    connect(actDelete, SIGNAL(triggered()), this, SLOT(onDelete()) );
    connect(actProp, SIGNAL(triggered()), this, SLOT(onProperties()) );

}

void BookmarksWidget::setupBookmarksSearchFields()
{
    ui->bookmarkSearchByButton->setPopupMode(QToolButton::InstantPopup);

    QMenu *searchByMenu = new QMenu(ui->bookmarkSearchByButton);

    QAction * actSearchByTD = searchByMenu->addAction(tr("By Title and Description"));
    actSearchByTD->setData(LibraryManager::SEARCH_BY_TITLE_DESCRIPTION);
    actSearchByTD->setCheckable(true);

    QAction * actSearchByT = searchByMenu->addAction(tr("By Title") );
    actSearchByT->setData(LibraryManager::SEARCH_BY_TITLE);
    actSearchByT->setCheckable(true);

    QAction * actSearchByD = searchByMenu->addAction(tr("By Description") );
    actSearchByD->setData(LibraryManager::SEARCH_BY_DESCRIPTION);
    actSearchByD->setCheckable(true);

    mActionSearchByContent = searchByMenu->addAction(tr("By Content") );
    mActionSearchByContent->setData(LibraryManager::SEARCH_BY_CONTENT);
    mActionSearchByContent->setCheckable(true);

    mActionsGroupSearchBy =  new QActionGroup(searchByMenu);
    mActionsGroupSearchBy->addAction(actSearchByTD);
    mActionsGroupSearchBy->addAction(actSearchByT);
    mActionsGroupSearchBy->addAction(actSearchByD);
    mActionsGroupSearchBy->addAction(mActionSearchByContent);

    actSearchByTD->setChecked(true);

    connect(mActionsGroupSearchBy, SIGNAL(triggered(QAction*)), this, SLOT(searchBookmarks()) );

    ui->bookmarkSearchByButton->setMenu(searchByMenu);

}
/*! This doesnt always work,
 * because the dropped files can be SVG, PDF, EPS, TXT
 *
void BookmarksWidget::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasUrls()){
        event->acceptProposedAction();

        ui->labelSearchImage->clear();
        ui->labelSearchImage->setText(tr("Drop Equation Here"));

        ui->widgetSearch->setVisible(false);
        ui->widgetSearchImage->setVisible(true);


    }
}

void BookmarksWidget::dragLeaveEvent(QDragLeaveEvent *event)
{
    if(!(ui->labelSearchImage->pixmap()) ){
        ui->widgetSearch->setVisible(true);
        ui->widgetSearchImage->setVisible(false);
    }
}

void BookmarksWidget::dropEvent(QDropEvent *ev)
{
    QUrl droppedUrl = ev->mimeData()->urls().at(0);

    if(!droppedUrl.isValid()) return;

    EqualX::FileInfo eqMetaData;

    QString filePath = droppedUrl.toLocalFile();
    if(!EqualX::File::fetchInfo(filePath, &eqMetaData)){
        qDebug() << "BookmarksWidget::dropEvent() Couldn't read File metadata!";
        ui->labelSearchImage->setText("Not an EqualX equation");
        return;
    }
    // dropped Url is an EqualX file

    // showing the equation
    QImage eqImg(filePath);

    eqImg = eqImg.scaled(QSize(134,134), Qt::KeepAspectRatio, Qt::SmoothTransformation);

    ui->labelSearchImage->setPixmap(QPixmap::fromImage(eqImg));

    // searching bookmarks
    ui->bookmarkSearchEdit->setText(eqMetaData.equation());
    mActionSearchByContent->setChecked(true);
    // signals are emitted and handled in searchBookmarks();
}
*/

void BookmarksWidget::onDoubleClick(const QModelIndex& index)
{
    LibraryModelData curRow = qvariant_cast<LibraryModelData>(index.data());

    if(curRow.isBookmark()){
        emit activated(curRow.id);
    }
}

void BookmarksWidget::onOpen()
{
    QModelIndex selected = ui->treeView->selectionModel()->currentIndex();
    if(!selected.isValid())
        return;

    LibraryModelData curRow = qvariant_cast<LibraryModelData>(selected.data());

    if(curRow.isFolder()){
        ui->treeView->setExpanded(selected, !ui->treeView->isExpanded(selected));
    }

    if(curRow.isBookmark()){
        emit activated(curRow.id);
    }
}

void BookmarksWidget::onNewFolder()
{
    LibraryManager::Instance()->addBookmarkFolder(tr("New Folder"));
}

void BookmarksWidget::onCut()
{
    onCopy();
    mIsCutActive = true;
}

void BookmarksWidget::onCopy()
{
    mIsCutActive = false;

    qDebug() << "onCopy()";

    QModelIndex selected = ui->treeView->selectionModel()->currentIndex();
    if(!selected.isValid())
        return;

    mCopiedRow = selected;
}

void BookmarksWidget::onPaste()
{
    qDebug() << "onPaste()";

    //const QModelIndexList indexList = ui->treeView->selectionModel()->selectedIndexes();
    QModelIndex selected = ui->treeView->selectionModel()->currentIndex();
    if(!selected.isValid() || !mCopiedRow.isValid())
        return;

    qDebug() << "BookmarksItemModel::copy()";

    BookmarkItem* item = mModel->itemFromIndex(mCopiedRow);
    BookmarkItem* parentItem = mModel->itemFromIndex(selected);

    if(!item || !parentItem)
        return;

    int itemId = item->data().id;
    int parentId = parentItem->data().id;

    switch(item->data().type){
    case LibraryModelData::TypeFolder:{
        LibraryManager::Instance()->copyBookmarkFolder(itemId, parentId);
        if(mIsCutActive){
            LibraryManager::Instance()->removeBookmarkFolder(itemId);
            mIsCutActive = false;
        }
        break;
    }
    case LibraryModelData::TypeBookmark:{
        LibraryManager::Instance()->copyBookmark(itemId, parentId);
        if(mIsCutActive){
            LibraryManager::Instance()->removeBookmark(itemId);
            mIsCutActive = false;
        }
        break;
    }
    default:
        break;
    }

}

void BookmarksWidget::onDelete()
{
    QModelIndex index = ui->treeView->selectionModel()->currentIndex();
    if(!index.isValid()) return;

    BookmarkItem* item = mModel->itemFromIndex(index);

    if(item->data().isFolder()) LibraryManager::Instance()->removeBookmarkFolder(item->data().id);
    if(item->data().isBookmark()) LibraryManager::Instance()->removeBookmark(item->data().id);

}

void BookmarksWidget::onProperties()
{
    QModelIndex selected = ui->treeView->selectionModel()->currentIndex();
    if(!selected.isValid())
        return;

    LibraryModelData itemData = mModel->itemFromIndex(selected)->data();

    if(itemData.isFolder()){
        BookmarkFolder folder = LibraryManager::Instance()->getBookmarkFolder(itemData.id);

        mDgPreferencesFolder->setName(folder.name);
        mDgPreferencesFolder->setDescription(folder.description);
        int status = mDgPreferencesFolder->exec();

        if(status==QDialog::Accepted){
            folder.name = mDgPreferencesFolder->name();
            folder.description = mDgPreferencesFolder->description();

            LibraryManager::Instance()->updateBookmarkFolder(folder);
        }

    } else if(itemData.isBookmark()){
        Bookmark b = LibraryManager::Instance()->getBookmark(itemData.id);

        mDgPreferencesBookmark->setTitle(b.title);
        mDgPreferencesBookmark->setDescrition(b.description);
        mDgPreferencesBookmark->setParentFolder(b.idparent);

        if(mDgPreferencesBookmark->exec()==QDialog::Accepted){
            int parentId = mDgPreferencesBookmark->parentFolder();

            b.title = mDgPreferencesBookmark->title();
            b.description=mDgPreferencesBookmark->description();

            LibraryManager::Instance()->updateBookmark(b);

            if(parentId != b.idparent){ // if parent changed
                LibraryManager::Instance()->moveBookmark(b.id, parentId);
                b.idparent = parentId;
            }
        }

    }
}

void BookmarksWidget::resetAutoSearchTimer(const QString &/*text*/)
{
    mAutoSearchTimer.start(400);
}

void BookmarksWidget::searchBookmarks()
{
    mAutoSearchTimer.stop();

    QString searchText = ui->bookmarkSearchEdit->text();
    qDebug() << "Searching bookmarks for:"<<searchText;
    if(searchText.isEmpty() || searchText.isNull()){
        ui->stackedWidget->setCurrentIndex(0);
        return;
    }

    mSearchModel->clear();
    ui->stackedWidget->setCurrentIndex(1);

    LibraryManager::SEARCH_MODE searchMode = (LibraryManager::SEARCH_MODE)mActionsGroupSearchBy->checkedAction()->data().toInt();

    LibraryRowsList rows = LibraryManager::Instance()->searchBookmarks(searchText, searchMode);

    if(rows.isEmpty()){
        //ui->stackedWidget->setCurrentIndex(0);

        return;
    }

    foreach(LibraryModelData row, rows){
        QStandardItem* item = new QStandardItem();
        item->setData(row, Qt::DisplayRole);

        mSearchModel->appendRow(item);
    }
}
