/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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/>  *
 ***************************************************************************/
/** @file
 * This file is a plugin for bookmarks management.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgbookmarkplugin.h"

#include <QtGui/QWidget>

#include <KActionCollection>
#include <KStandardDirs>
#include <KToolBarPopupAction>
#include <KAboutData>
#include <KGenericFactory>

#include "skgbookmark_settings.h"
#include "skgtraces.h"
#include "skgerror.h"
#include "skgmainpanel.h"
#include "skgservices.h"
#include "skgnodeobject.h"
#include "skgtransactionmng.h"
#include "skgbookmarkplugindockwidget.h"

/**
 * This plugin factory.
 */
K_PLUGIN_FACTORY(SKGBookmarkPluginFactory, registerPlugin<SKGBookmarkPlugin>();)
/**
 * This plugin export.
 */
K_EXPORT_PLUGIN(SKGBookmarkPluginFactory("skg_bookmark", "skg_bookmark"))

SKGBookmarkPlugin::SKGBookmarkPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& iArg) :
    SKGInterfacePlugin(iParent), m_currentDocument(NULL), m_dockWidget(NULL), m_importStdBookmarkAction(NULL), m_bookmarkAction(NULL), m_bookmarkMenu(NULL)
{
    Q_UNUSED(iArg);
    Q_UNUSED(iWidget);
    SKGTRACEINFUNC(10);
}

SKGBookmarkPlugin::~SKGBookmarkPlugin()
{
    SKGTRACEINFUNC(10);
    m_currentDocument = NULL;
    m_dockWidget = NULL;
    m_importStdBookmarkAction = NULL;
    m_bookmarkAction = NULL;
    m_bookmarkMenu = NULL;
}

bool SKGBookmarkPlugin::setupActions(SKGDocument* iDocument, const QStringList& iArgument)
{
    SKGTRACEINFUNC(10);
    Q_UNUSED(iArgument);

    m_currentDocument = iDocument;

    setComponentData(KGlobal::mainComponent());
    setXMLFile("../skg_bookmark/skg_bookmark.rc");

    m_dockWidget = new QDockWidget(SKGMainPanel::getMainPanel());
    m_dockWidget->setObjectName(QString::fromUtf8("skg_bookmark_docwidget"));
    m_dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_dockWidget->setWindowTitle(title());
    m_dockWidget->setWidget(new SKGBookmarkPluginDockWidget(m_currentDocument));

    // add action to control hide / display of Bookmarks
    QAction* toggle = m_dockWidget->toggleViewAction();
    KAction* panelAction = actionCollection()->addAction("view_bookmarks");
    registerGlobalAction("view_bookmarks", panelAction);
    panelAction->setCheckable(true);
    panelAction->setChecked(toggle->isChecked());
    panelAction->setText(toggle->text());
    panelAction->setShortcut(Qt::SHIFT + Qt::Key_F10);
    connect(panelAction, SIGNAL(triggered()), toggle, SLOT(trigger()));
    connect(toggle, SIGNAL(toggled(bool)), panelAction, SLOT(setChecked(bool)));

    // Import bookmarks
    QStringList overlaybookmarks;
    overlaybookmarks.push_back(icon());

    m_importStdBookmarkAction = new KAction(KIcon("document-import", NULL, overlaybookmarks), i18nc("Verb", "Import standard bookmarks"), this);
    connect(m_importStdBookmarkAction, SIGNAL(triggered(bool)), SLOT(importStandardBookmarks()));
    registerGlobalAction("import_standard_bookmarks", m_importStdBookmarkAction);

    //
    KAction* goHomeAction = KStandardAction::home(this, SLOT(goHome()), actionCollection());
    goHomeAction->setPriority(QAction::LowPriority);
    registerGlobalAction("go_home", goHomeAction);

    // Bookmark
    m_bookmarkAction = new KToolBarPopupAction(KIcon("bookmark-new-list"), i18nc("Verb, action to display bookmarks", "Bookmarks"), this);
    connect(m_bookmarkAction, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(onOpenBookmark()));
    m_bookmarkMenu = static_cast<KMenu*>(m_bookmarkAction->menu());
    if (m_bookmarkMenu) {
        m_bookmarkMenu->setProperty("id", 0);
        connect(m_bookmarkMenu , SIGNAL(aboutToShow()), this, SLOT(onShowBookmarkMenu()));
    }

    m_bookmarkAction->setStickyMenu(false);
    m_bookmarkAction->setDelayed(false);
    m_bookmarkAction->setData(0);
    m_bookmarkAction->setPriority(QAction::LowPriority);

    // bookmarkAction=KStandardAction::redo(this, SLOT(onRedo()), actionCollection());
    registerGlobalAction("edit_bookmark", m_bookmarkAction);

    return true;
}

QWidget* SKGBookmarkPlugin::getPreferenceWidget()
{
    SKGTRACEINFUNC(10);
    QWidget* w = new QWidget();
    ui.setupUi(w);
    return w;
}

KConfigSkeleton* SKGBookmarkPlugin::getPreferenceSkeleton()
{
    return skgbookmark_settings::self();
}

void SKGBookmarkPlugin::refresh()
{
    SKGTRACEINFUNC(10);
    if (m_dockWidget) {
        SKGBookmarkPluginDockWidget* p = static_cast<SKGBookmarkPluginDockWidget*>(m_dockWidget->widget());
        if (p) {
            p->refresh();
        }
    }

    if (m_currentDocument) {
        bool test = (m_currentDocument->getDatabase() != NULL);
        if (m_importStdBookmarkAction) {
            m_importStdBookmarkAction->setEnabled(test);
        }

        // Automatic bookmarks creation
        if (m_currentDocument->getDatabase() != NULL) {
            QString doc_id = m_currentDocument->getUniqueIdentifier();
            if (m_docUniqueIdentifier != doc_id) {
                m_docUniqueIdentifier = doc_id;

                bool exist = false;
                SKGError err = m_currentDocument->existObjects("node", "", exist);
                if (!err && !exist) {
                    importStandardBookmarks();

                    // The file is considered has not modified
                    m_currentDocument->setFileNotModified();
                }

                // Automatic open of autostart bookmark
                if (!err && !(QApplication::keyboardModifiers() &Qt::ShiftModifier)) {
                    goHome();
                }
            }
        }
    }
}

QString SKGBookmarkPlugin::title() const
{
    return i18nc("Noun, a bookmark as in a webbrowser bookmark", "Bookmarks");
}

QString SKGBookmarkPlugin::icon() const
{
    return "bookmarks";
}

QStringList SKGBookmarkPlugin::tips() const
{
    QStringList output;
    output.push_back(i18nc("Description of a tips", "<p>... some bookmarks can be opened automatically when the application is launched.</p>"));
    output.push_back(i18nc("Description of a tips", "<p>... bookmarks can be reorganized by drag & drop.</p>"));
    output.push_back(i18nc("Description of a tips", "<p>... a double click on a folder of bookmarks will open all the bookmarks it contains.</p>"));
    output.push_back(i18nc("Description of a tips", "<p>... you can import standard bookmarks.</p>"));
    return output;
}

int SKGBookmarkPlugin::getOrder() const
{
    return 3;
}

QDockWidget* SKGBookmarkPlugin::getDockWidget()
{
    return m_dockWidget;
}

void SKGBookmarkPlugin::importStandardBookmarks()
{
    SKGTRACEINFUNC(10);
    SKGError err;
    SKGBEGINTRANSACTION(*m_currentDocument, i18nc("Noun, name of the user action", "Import standard bookmarks"), err);

    // TODO(Stephane MANKOWSKI): Must be generic
    QStringList bks;
    bks << i18nc("Noun, bookmark name", "Dashboard") % "|N|dashboard-show|\"Dashboard plugin\";\"Dashboard\";\"<!DOCTYPE SKGML><parameters zoomPosition=\"\"0\"\"> <ITEM-1 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge bank plugin\"\" state=\"\"&lt;!DOCTYPE SKGML>&#xa;&lt;parameters menuOther=&quot;Y&quot; menuCurrent=&quot;Y&quot; menuFavorite=&quot;N&quot; menuAssets=&quot;Y&quot; menuInvestment=&quot;Y&quot; menuCreditCard=&quot;Y&quot;/>&#xa;\"\"/> <ITEM-2 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge operation plugin\"\" state=\"\"&lt;!DOCTYPE SKGML>"
        "&#xa;&lt;parameters menuTransfert=&quot;Y&quot;/>&#xa;\"\"/> <ITEM-3 zoom=\"\"0\"\" index=\"\"1\"\" name=\"\"Skrooge operation plugin\"\" state=\"\"\"\"/> <ITEM-4 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge scheduled plugin\"\" state=\"\"\"\"/> <ITEM-5 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge search plugin\"\" state=\"\"&lt;!DOCTYPE SKGML>"
        "&#xa;&lt;parameters menuFavorite=&quot;N&quot;/>&#xa;\"\"/> <ITEM-6 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge unit plugin\"\" state=\"\"&lt;!DOCTYPE SKGML>&#xa;&lt;parameters menuShares=&quot;Y&quot; menuSharesOwnedOnly=&quot;N&quot; menuIndexes=&quot;Y&quot;/>&#xa;\"\"/> <ITEM-7 zoom=\"\"0\"\" index=\"\"0\"\" name=\"\"Skrooge calculator plugin\"\" state=\"\"\"\"/></parameters>\""
        << i18nc("Noun, bookmark name", "Report > Income vs Expenditure on 12 last months") % "|N|view-investment|\"Skrooge report plugin\";\"Rapport\";\"<!DOCTYPE SKGML><parameters  expenses=\"\"Y\"\" tableAndGraphState=\"\"&lt;!DOCTYPE SKGML>"
        "&#xa;&lt;parameters graphMode=&quot;1&quot; graphicViewState=&quot;&amp;lt;!DOCTYPE SKGML>&amp;#xa;&amp;lt;parameters isToolBarVisible=&amp;quot;Y&amp;quot; antialiasing=&amp;quot;Y&amp;quot;/>&amp;#xa;&quot; splitterState=&quot;000000ff00000000000000020000025b0000032901000000060100000001&quot; bottomToolBarVisible=&quot;Y&quot; filter=&quot;&quot; legendVisible=&quot;N&quot; allPositive=&quot;Y&quot; linearRegressionVisible=&quot;Y&quot; sortColumn=&quot;0&quot; limitVisible=&quot;Y&quot; web=&quot;&amp;lt;!DOCTYPE SKGML>"
        "&amp;#xa;&amp;lt;parameters zoomFactor=&amp;quot;0&amp;quot;/>&amp;#xa;&quot; sortOrder=&quot;0&quot;/>&#xa;\"\" mode=\"\"0\"\" period=\"\"3\"\" incomes=\"\"Y\"\" interval=\"\"2\"\" lines=\"\"t_TYPEEXPENSENLS\"\" lines2=\"\"#NOTHING#\"\" nbLevelLines=\"\"0\"\" nbLevelColumns=\"\"0\"\" forecast=\"\"0\"\" columns=\"\"d_DATEMONTH\"\" nb_intervals=\"\"12\"\" forecastValue=\"\"20\"\" transfers=\"\"N\"\" currentPage=\"\"0\"\"/>\""
        << i18nc("Noun, bookmark name", "Report > Pie categories in 12 last months") % "|N|view-investment|\"Skrooge report plugin\";\"Rapport\";\"<!DOCTYPE SKGML><parameters expenses=\"\"Y\"\" tableAndGraphState=\"\"&lt;!DOCTYPE SKGML>&#xa;&lt;parameters graphMode=&quot;2&quot; graphicViewState=&quot;&amp;lt;!DOCTYPE SKGML>"
        "&amp;#xa;&amp;lt;parameters isToolBarVisible=&amp;quot;Y&amp;quot; antialiasing=&amp;quot;Y&amp;quot;/>&amp;#xa;&quot; splitterState=&quot;000000ff00000000000000020000025b0000032901000000060100000001&quot; bottomToolBarVisible=&quot;Y&quot; filter=&quot;&quot; legendVisible=&quot;N&quot; allPositive=&quot;Y&quot; linearRegressionVisible=&quot;Y&quot; sortColumn=&quot;-1&quot; limitVisible=&quot;Y&quot; web=&quot;&amp;lt;!DOCTYPE SKGML>"
        "&amp;#xa;&amp;lt;parameters zoomFactor=&amp;quot;0&amp;quot;/>&amp;#xa;&quot; sortOrder=&quot;0&quot;/>&#xa;\"\" mode=\"\"0\"\" period=\"\"3\"\" incomes=\"\"Y\"\" interval=\"\"2\"\" lines=\"\"t_REALCATEGORY\"\" lines2=\"\"#NOTHING#\"\" nbLevelLines=\"\"0\"\" nbLevelColumns=\"\"0\"\" forecast=\"\"0\"\" columns=\"\"d_DATEMONTH\"\" nb_intervals=\"\"12\"\" forecastValue=\"\"20\"\" transfers=\"\"N\"\" currentPage=\"\"0\"\"/>\""
        << i18nc("Noun, bookmark name", "Report > History") % "|N|view-investment|\"Skrooge report plugin\";\"Rapport\";\"<!DOCTYPE SKGML><parameters expenses=\"\"Y\"\" tableAndGraphState=\"\"&lt;!DOCTYPE SKGML>"
        "&#xa;&lt;parameters graphMode=&quot;1&quot; graphicViewState=&quot;&amp;lt;!DOCTYPE SKGML>&amp;#xa;&amp;lt;parameters isToolBarVisible=&amp;quot;Y&amp;quot; antialiasing=&amp;quot;Y&amp;quot;/>&amp;#xa;&quot; splitterState=&quot;000000ff0000000000000002000002b50000032601000000060100000001&quot; bottomToolBarVisible=&quot;Y&quot; filter=&quot;&quot; legendVisible=&quot;N&quot; allPositive=&quot;N&quot; linearRegressionVisible=&quot;Y&quot; sortColumn=&quot;-1&quot; limitVisible=&quot;Y&quot; web=&quot;&amp;lt;!DOCTYPE SKGML>"
        "&amp;#xa;&amp;lt;parameters zoomFactor=&amp;quot;0&amp;quot;/>&amp;#xa;&quot; sortOrder=&quot;0&quot;/>&#xa;\"\" mode=\"\"1\"\" period=\"\"0\"\" incomes=\"\"Y\"\" interval=\"\"2\"\" lines=\"\"#NOTHING#\"\" lines2=\"\"#NOTHING#\"\" nbLevelLines=\"\"0\"\" nbLevelColumns=\"\"0\"\" forecast=\"\"0\"\" columns=\"\"d_DATEMONTH\"\" nb_intervals=\"\"1\"\" forecastValue=\"\"20\"\" transfers=\"\"Y\"\" currentPage=\"\"0\"\"/>\"";


    foreach(const QString & bk, bks) {
        QStringList line = SKGServices::splitCSVLine(bk, '|', false);
        if (line.count() == 4) {
            SKGNodeObject node;
            err = SKGNodeObject::createPathNode(m_currentDocument, line.at(0), node);
            IFOKDO(err, node.setAutoStart(line.at(1) == "Y"))
            IFOKDO(err, node.setIcon(line.at(2)))
            IFOKDO(err, node.setData(line.at(3)))
            IFOKDO(err, node.save())
        }
    }

    // status
    IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Standard bookmarks imported.")))
    else {
        err.addError(ERR_FAIL, i18nc("Error message",  "Import standard bookmarks failed"));
    }

    // Display error
    SKGMainPanel::displayErrorMessage(err);
}

void SKGBookmarkPlugin::goHome()
{
    if (SKGMainPanel::getMainPanel()) {
        SKGMainPanel::getMainPanel()->closeAllPages(false);    // Home do not close pinned pages
    }

    SKGObjectBase::SKGListSKGObjectBase oNodeList;
    if (m_currentDocument) {
        m_currentDocument->getObjects("v_node", "t_autostart='Y' ORDER BY f_sortorder, t_name", oNodeList);
    }
    int nbAutoStartedBookmarks = oNodeList.count();
    for (int i = 0; i < nbAutoStartedBookmarks; ++i) {
        SKGNodeObject autostarted_bookmark(oNodeList.at(i));
        autostarted_bookmark.load();
        SKGTRACEIN(10, "autostarting bookmark : " % autostarted_bookmark.getName());
        SKGBookmarkPluginDockWidget::openBookmark(autostarted_bookmark, i > 0, true);
    }
}

void SKGBookmarkPlugin::onOpenBookmark(Qt::MouseButtons iMouse, Qt::KeyboardModifiers iKeyboard)
{
    QAction* callerAction = qobject_cast<QAction*>(this->sender());
    if (callerAction) {
        SKGNodeObject node(m_currentDocument, callerAction->data().toInt());
        SKGBookmarkPluginDockWidget::openBookmark(node, iMouse & Qt::MidButton || iKeyboard & Qt::ControlModifier);
    }
}

void SKGBookmarkPlugin::onAddBookmark()
{
    SKGTRACEINFUNC(1);
    SKGError err;

    // Get current page
    SKGNodeObject node;
    {
        // Get current selection
        SKGNodeObject parentNode;
        QAction* callerAction = qobject_cast<QAction*>(this->sender());
        if (callerAction) {
            parentNode = SKGNodeObject(m_currentDocument, callerAction->data().toInt());
        }

        // Create bookmark
        err =  SKGBookmarkPluginDockWidget::createNodeFromPage(SKGMainPanel::getMainPanel()->currentPage(), parentNode, node);
    }
    // status bar
    IFOK(err) {
        err = SKGError(0, i18nc("Successful message after an user action", "Bookmark created"));
    }
    SKGMainPanel::displayErrorMessage(err);
}

void SKGBookmarkPlugin::onShowBookmarkMenu()
{
    KMenu* callerMenu = qobject_cast<KMenu*>(this->sender());
    if (callerMenu && m_currentDocument) {
        // Remove previous menu
        callerMenu->clear();

        // Build query
        QString wc = "rd_node_id=0 OR rd_node_id IS NULL OR rd_node_id=''";
        int idParent = callerMenu->property("id").toInt();
        if (idParent != 0) {
            wc = "rd_node_id=" % SKGServices::intToString(idParent);
        }

        // Build new menu
        SKGObjectBase::SKGListSKGObjectBase listNode;
        m_currentDocument->getObjects("v_node", wc % " ORDER BY f_sortorder, t_name", listNode);
        int nb = listNode.count();
        for (int i = 0; i < nb; ++i) {
            SKGNodeObject node(listNode.at(i));
            if (node.isFolder()) {
                // This is a folder
                KMenu* menu = new KMenu(callerMenu);
                if (menu) {
                    callerMenu->addMenu(menu);
                    menu->setTitle(node.getName());
                    menu->setIcon(node.getIcon());
                    menu->setProperty("id", node.getID());
                    connect(menu , SIGNAL(aboutToShow()), this, SLOT(onShowBookmarkMenu()));
                }
            } else {
                // This is a bookmark
                KAction* act = new KAction(callerMenu);
                if (act) {
                    callerMenu->addAction(act);
                    act->setText(node.getName());
                    act->setIcon(node.getIcon());
                    act->setData(node.getID());
                    connect(act, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(onOpenBookmark(Qt::MouseButtons,Qt::KeyboardModifiers)));
                }
            }
        }

        // Add separator
        QAction* sep = new QAction(this);
        sep->setSeparator(true);
        callerMenu->addAction(sep);

        // This common actions
        {
            // Open all
            KAction* act = new KAction(callerMenu);
            if (act) {
                callerMenu->addAction(act);
                act->setText(i18nc("Action", "Open all"));
                act->setIcon(KIcon("skg_open"));
                act->setData(idParent);
                connect(act, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(onOpenBookmark(Qt::MouseButtons,Qt::KeyboardModifiers)));
            }
            if (SKGMainPanel::getMainPanel()->currentPageIndex() >= 0) {
                // Bookmark current here
                KAction* act2 = new KAction(callerMenu);
                if (act2) {
                    callerMenu->addAction(act2);
                    act2->setText(i18nc("Action", "Bookmark current page here"));
                    act2->setIcon(KIcon("list-add"));
                    act2->setData(idParent);

                    connect(act2, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), this, SLOT(onAddBookmark()));
                }
            }
        }
    }
}


#include "skgbookmarkplugin.moc"
